コード例 #1
0
ファイル: basetabs.py プロジェクト: lasse-aagren/poezio
    def __init__(self, jid=''):
        Tab.__init__(self)
        self.name = jid
        self.text_win = None
        self._text_buffer = TextBuffer()
        self.chatstate = None  # can be "active", "composing", "paused", "gone", "inactive"
        # We keep a reference of the event that will set our chatstate to "paused", so that
        # we can delete it or change it if we need to
        self.timed_event_paused = None
        # Keeps the last sent message to complete it easily in completion_correct, and to replace it.
        self.last_sent_message = None
        self.key_func['M-v'] = self.move_separator
        self.key_func['M-h'] = self.scroll_separator
        self.key_func['M-/'] = self.last_words_completion
        self.key_func['^M'] = self.on_enter
        self.register_command('say',
                              self.command_say,
                              usage='<message>',
                              shortdesc='Send the message.')
        self.register_command('xhtml',
                              self.command_xhtml,
                              usage='<custom xhtml>',
                              shortdesc='Send custom XHTML.')
        self.register_command('clear',
                              self.command_clear,
                              shortdesc='Clear the current buffer.')
        self.register_command(
            'correct',
            self.command_correct,
            desc='Fix the last message with whatever you want.',
            shortdesc='Correct the last message.',
            completion=self.completion_correct)
        self.chat_state = None
        self.update_commands()
        self.update_keys()

        # Get the logs
        log_nb = config.get('load_log')
        logs = self.load_logs(log_nb)

        if logs:
            for message in logs:
                self._text_buffer.add_message(**message)
コード例 #2
0
ファイル: basetabs.py プロジェクト: Perdu/poezio
    def __init__(self, jid=''):
        Tab.__init__(self)
        self.name = jid
        self.text_win = None
        self._text_buffer = TextBuffer()
        self.chatstate = None   # can be "active", "composing", "paused", "gone", "inactive"
        # We keep a reference of the event that will set our chatstate to "paused", so that
        # we can delete it or change it if we need to
        self.timed_event_paused = None
        # Keeps the last sent message to complete it easily in completion_correct, and to replace it.
        self.last_sent_message = None
        self.key_func['M-v'] = self.move_separator
        self.key_func['M-h'] = self.scroll_separator
        self.key_func['M-/'] = self.last_words_completion
        self.key_func['^M'] = self.on_enter
        self.register_command('say', self.command_say,
                usage=_('<message>'),
                shortdesc=_('Send the message.'))
        self.register_command('xhtml', self.command_xhtml,
                usage=_('<custom xhtml>'),
                shortdesc=_('Send custom XHTML.'))
        self.register_command('clear', self.command_clear,
                shortdesc=_('Clear the current buffer.'))
        self.register_command('correct', self.command_correct,
                desc=_('Fix the last message with whatever you want.'),
                shortdesc=_('Correct the last message.'),
                completion=self.completion_correct)
        self.chat_state = None
        self.update_commands()
        self.update_keys()

        # Get the logs
        log_nb = config.get('load_log')
        logs = self.load_logs(log_nb)

        if logs:
            for message in logs:
                self._text_buffer.add_message(**message)
コード例 #3
0
ファイル: basetabs.py プロジェクト: Perdu/poezio
class ChatTab(Tab):
    """
    A tab containing a chat of any type.
    Just use this class instead of Tab if the tab needs a recent-words completion
    Also, ^M is already bound to on_enter
    And also, add the /say command
    """
    plugin_commands = {}
    plugin_keys = {}
    def __init__(self, jid=''):
        Tab.__init__(self)
        self.name = jid
        self.text_win = None
        self._text_buffer = TextBuffer()
        self.chatstate = None   # can be "active", "composing", "paused", "gone", "inactive"
        # We keep a reference of the event that will set our chatstate to "paused", so that
        # we can delete it or change it if we need to
        self.timed_event_paused = None
        # Keeps the last sent message to complete it easily in completion_correct, and to replace it.
        self.last_sent_message = None
        self.key_func['M-v'] = self.move_separator
        self.key_func['M-h'] = self.scroll_separator
        self.key_func['M-/'] = self.last_words_completion
        self.key_func['^M'] = self.on_enter
        self.register_command('say', self.command_say,
                usage=_('<message>'),
                shortdesc=_('Send the message.'))
        self.register_command('xhtml', self.command_xhtml,
                usage=_('<custom xhtml>'),
                shortdesc=_('Send custom XHTML.'))
        self.register_command('clear', self.command_clear,
                shortdesc=_('Clear the current buffer.'))
        self.register_command('correct', self.command_correct,
                desc=_('Fix the last message with whatever you want.'),
                shortdesc=_('Correct the last message.'),
                completion=self.completion_correct)
        self.chat_state = None
        self.update_commands()
        self.update_keys()

        # Get the logs
        log_nb = config.get('load_log')
        logs = self.load_logs(log_nb)

        if logs:
            for message in logs:
                self._text_buffer.add_message(**message)

    @property
    def is_muc(self):
        return False

    def load_logs(self, log_nb):
        logs = logger.get_logs(safeJID(self.name).bare, log_nb)
        return logs

    def log_message(self, txt, nickname, time=None, typ=1):
        """
        Log the messages in the archives.
        """
        name = safeJID(self.name).bare
        if not logger.log_message(name, nickname, txt, date=time, typ=typ):
            self.core.information(_('Unable to write in the log file'), 'Error')

    def add_message(self, txt, time=None, nickname=None, forced_user=None,
                    nick_color=None, identifier=None, jid=None, history=None,
                    typ=1, highlight=False):
        self.log_message(txt, nickname, time=time, typ=typ)
        self._text_buffer.add_message(txt, time=time,
                nickname=nickname,
                highlight=highlight,
                nick_color=nick_color,
                history=history,
                user=forced_user,
                identifier=identifier,
                jid=jid)

    def modify_message(self, txt, old_id, new_id, user=None, jid=None, nickname=None):
        self.log_message(txt, nickname, typ=1)
        message = self._text_buffer.modify_message(txt, old_id, new_id, time=time, user=user, jid=jid)
        if message:
            self.text_win.modify_message(old_id, message)
            self.core.refresh_window()
            return True
        return False

    def last_words_completion(self):
        """
        Complete the input with words recently said
        """
        # build the list of the recent words
        char_we_dont_want = string.punctuation+' ’„“”…«»'
        words = list()
        for msg in self._text_buffer.messages[:-40:-1]:
            if not msg:
                continue
            txt = xhtml.clean_text(msg.txt)
            for char in char_we_dont_want:
                txt = txt.replace(char, ' ')
            for word in txt.split():
                if len(word) >= 4 and word not in words:
                    words.append(word)
        words.extend([word for word in config.get('words').split(':') if word])
        self.input.auto_completion(words, ' ', quotify=False)

    def on_enter(self):
        txt = self.input.key_enter()
        if txt:
            if not self.execute_command(txt):
                if txt.startswith('//'):
                    txt = txt[1:]
                self.command_say(xhtml.convert_simple_to_full_colors(txt))
        self.cancel_paused_delay()

    @command_args_parser.raw
    def command_xhtml(self, xhtml):
        """"
        /xhtml <custom xhtml>
        """
        message = self.generate_xhtml_message(xhtml)
        if message:
            message.send()

    def generate_xhtml_message(self, arg):
        if not arg:
            return
        try:
            body = xhtml.clean_text(xhtml.xhtml_to_poezio_colors(arg))
            ET.fromstring(arg)
        except:
            self.core.information('Could not send custom xhtml', 'Error')
            log.error('/xhtml: Unable to send custom xhtml', exc_info=True)
            return

        msg = self.core.xmpp.make_message(self.get_dest_jid())
        msg['body'] = body
        msg.enable('html')
        msg['html']['body'] = arg
        return msg

    def get_dest_jid(self):
        return self.name

    @refresh_wrapper.always
    def command_clear(self, ignored):
        """
        /clear
        """
        self._text_buffer.messages = []
        self.text_win.rebuild_everything(self._text_buffer)

    def send_chat_state(self, state, always_send=False):
        """
        Send an empty chatstate message
        """
        if not self.is_muc or self.joined:
            if state in ('active', 'inactive', 'gone') and self.inactive and not always_send:
                return
            if (config.get_by_tabname('send_chat_states', self.general_jid)
                    and self.remote_wants_chatstates is not False):
                msg = self.core.xmpp.make_message(self.get_dest_jid())
                msg['type'] = self.message_type
                msg['chat_state'] = state
                self.chat_state = state
                msg.send()
                return True

    def send_composing_chat_state(self, empty_after):
        """
        Send the "active" or "composing" chatstate, depending
        on the the current status of the input
        """
        name = self.general_jid
        if (config.get_by_tabname('send_chat_states', name)
                and self.remote_wants_chatstates):
            needed = 'inactive' if self.inactive else 'active'
            self.cancel_paused_delay()
            if not empty_after:
                if self.chat_state != "composing":
                    self.send_chat_state("composing")
                self.set_paused_delay(True)
            elif empty_after and self.chat_state != needed:
                self.send_chat_state(needed, True)

    def set_paused_delay(self, composing):
        """
        we create a timed event that will put us to paused
        in a few seconds
        """
        if not config.get_by_tabname('send_chat_states', self.general_jid):
            return
        # First, cancel the delay if it already exists, before rescheduling
        # it at a new date
        self.cancel_paused_delay()
        new_event = timed_events.DelayedEvent(4, self.send_chat_state, 'paused')
        self.core.add_timed_event(new_event)
        self.timed_event_paused = new_event

    def cancel_paused_delay(self):
        """
        Remove that event from the list and set it to None.
        Called for example when the input is emptied, or when the message
        is sent
        """
        if self.timed_event_paused is not None:
            self.core.remove_timed_event(self.timed_event_paused)
            self.timed_event_paused = None

    @command_args_parser.raw
    def command_correct(self, line):
        """
        /correct <fixed message>
        """
        if not line:
            self.core.command_help('correct')
            return
        if not self.last_sent_message:
            self.core.information(_('There is no message to correct.'))
            return
        self.command_say(line, correct=True)

    def completion_correct(self, the_input):
        if self.last_sent_message and the_input.get_argument_position() == 1:
            return the_input.auto_completion([self.last_sent_message['body']], '', quotify=False)

    @property
    def inactive(self):
        """Whether we should send inactive or active as a chatstate"""
        return self.core.status.show in ('xa', 'away') or\
                (hasattr(self, 'directed_presence') and not self.directed_presence)

    def move_separator(self):
        self.text_win.remove_line_separator()
        self.text_win.add_line_separator(self._text_buffer)
        self.text_win.refresh()
        self.input.refresh()

    def get_conversation_messages(self):
        return self._text_buffer.messages

    def check_scrolled(self):
        if self.text_win.pos != 0:
            self.state = 'scrolled'

    @command_args_parser.raw
    def command_say(self, line, correct=False):
        pass

    def on_line_up(self):
        return self.text_win.scroll_up(1)

    def on_line_down(self):
        return self.text_win.scroll_down(1)

    def on_scroll_up(self):
        return self.text_win.scroll_up(self.text_win.height-1)

    def on_scroll_down(self):
        return self.text_win.scroll_down(self.text_win.height-1)

    def on_half_scroll_up(self):
        return self.text_win.scroll_up((self.text_win.height-1) // 2)

    def on_half_scroll_down(self):
        return self.text_win.scroll_down((self.text_win.height-1) // 2)

    @refresh_wrapper.always
    def scroll_separator(self):
        self.text_win.scroll_to_separator()
コード例 #4
0
ファイル: basetabs.py プロジェクト: lasse-aagren/poezio
class ChatTab(Tab):
    """
    A tab containing a chat of any type.
    Just use this class instead of Tab if the tab needs a recent-words completion
    Also, ^M is already bound to on_enter
    And also, add the /say command
    """
    plugin_commands = {}
    plugin_keys = {}

    def __init__(self, jid=''):
        Tab.__init__(self)
        self.name = jid
        self.text_win = None
        self._text_buffer = TextBuffer()
        self.chatstate = None  # can be "active", "composing", "paused", "gone", "inactive"
        # We keep a reference of the event that will set our chatstate to "paused", so that
        # we can delete it or change it if we need to
        self.timed_event_paused = None
        # Keeps the last sent message to complete it easily in completion_correct, and to replace it.
        self.last_sent_message = None
        self.key_func['M-v'] = self.move_separator
        self.key_func['M-h'] = self.scroll_separator
        self.key_func['M-/'] = self.last_words_completion
        self.key_func['^M'] = self.on_enter
        self.register_command('say',
                              self.command_say,
                              usage='<message>',
                              shortdesc='Send the message.')
        self.register_command('xhtml',
                              self.command_xhtml,
                              usage='<custom xhtml>',
                              shortdesc='Send custom XHTML.')
        self.register_command('clear',
                              self.command_clear,
                              shortdesc='Clear the current buffer.')
        self.register_command(
            'correct',
            self.command_correct,
            desc='Fix the last message with whatever you want.',
            shortdesc='Correct the last message.',
            completion=self.completion_correct)
        self.chat_state = None
        self.update_commands()
        self.update_keys()

        # Get the logs
        log_nb = config.get('load_log')
        logs = self.load_logs(log_nb)

        if logs:
            for message in logs:
                self._text_buffer.add_message(**message)

    @property
    def is_muc(self):
        return False

    def load_logs(self, log_nb):
        logs = logger.get_logs(safeJID(self.name).bare, log_nb)
        return logs

    def log_message(self, txt, nickname, time=None, typ=1):
        """
        Log the messages in the archives.
        """
        name = safeJID(self.name).bare
        if not logger.log_message(name, nickname, txt, date=time, typ=typ):
            self.core.information('Unable to write in the log file', 'Error')

    def add_message(self,
                    txt,
                    time=None,
                    nickname=None,
                    forced_user=None,
                    nick_color=None,
                    identifier=None,
                    jid=None,
                    history=None,
                    typ=1,
                    highlight=False):
        self.log_message(txt, nickname, time=time, typ=typ)
        self._text_buffer.add_message(txt,
                                      time=time,
                                      nickname=nickname,
                                      highlight=highlight,
                                      nick_color=nick_color,
                                      history=history,
                                      user=forced_user,
                                      identifier=identifier,
                                      jid=jid)

    def modify_message(self,
                       txt,
                       old_id,
                       new_id,
                       user=None,
                       jid=None,
                       nickname=None):
        self.log_message(txt, nickname, typ=1)
        message = self._text_buffer.modify_message(txt,
                                                   old_id,
                                                   new_id,
                                                   time=time,
                                                   user=user,
                                                   jid=jid)
        if message:
            self.text_win.modify_message(old_id, message)
            self.core.refresh_window()
            return True
        return False

    def last_words_completion(self):
        """
        Complete the input with words recently said
        """
        # build the list of the recent words
        char_we_dont_want = string.punctuation + ' ’„“”…«»'
        words = list()
        for msg in self._text_buffer.messages[:-40:-1]:
            if not msg:
                continue
            txt = xhtml.clean_text(msg.txt)
            for char in char_we_dont_want:
                txt = txt.replace(char, ' ')
            for word in txt.split():
                if len(word) >= 4 and word not in words:
                    words.append(word)
        words.extend([word for word in config.get('words').split(':') if word])
        self.input.auto_completion(words, ' ', quotify=False)

    def on_enter(self):
        txt = self.input.key_enter()
        if txt:
            if not self.execute_command(txt):
                if txt.startswith('//'):
                    txt = txt[1:]
                self.command_say(xhtml.convert_simple_to_full_colors(txt))
        self.cancel_paused_delay()

    @command_args_parser.raw
    def command_xhtml(self, xhtml):
        """"
        /xhtml <custom xhtml>
        """
        message = self.generate_xhtml_message(xhtml)
        if message:
            message.send()

    def generate_xhtml_message(self, arg):
        if not arg:
            return
        try:
            body = xhtml.clean_text(xhtml.xhtml_to_poezio_colors(arg))
            ET.fromstring(arg)
        except:
            self.core.information('Could not send custom xhtml', 'Error')
            log.error('/xhtml: Unable to send custom xhtml', exc_info=True)
            return

        msg = self.core.xmpp.make_message(self.get_dest_jid())
        msg['body'] = body
        msg.enable('html')
        msg['html']['body'] = arg
        return msg

    def get_dest_jid(self):
        return self.name

    @refresh_wrapper.always
    def command_clear(self, ignored):
        """
        /clear
        """
        self._text_buffer.messages = []
        self.text_win.rebuild_everything(self._text_buffer)

    def send_chat_state(self, state, always_send=False):
        """
        Send an empty chatstate message
        """
        if not self.is_muc or self.joined:
            if state in ('active', 'inactive',
                         'gone') and self.inactive and not always_send:
                return
            if (config.get_by_tabname('send_chat_states', self.general_jid)
                    and self.remote_wants_chatstates is not False):
                msg = self.core.xmpp.make_message(self.get_dest_jid())
                msg['type'] = self.message_type
                msg['chat_state'] = state
                self.chat_state = state
                msg.send()
                return True

    def send_composing_chat_state(self, empty_after):
        """
        Send the "active" or "composing" chatstate, depending
        on the the current status of the input
        """
        name = self.general_jid
        if (config.get_by_tabname('send_chat_states', name)
                and self.remote_wants_chatstates):
            needed = 'inactive' if self.inactive else 'active'
            self.cancel_paused_delay()
            if not empty_after:
                if self.chat_state != "composing":
                    self.send_chat_state("composing")
                self.set_paused_delay(True)
            elif empty_after and self.chat_state != needed:
                self.send_chat_state(needed, True)

    def set_paused_delay(self, composing):
        """
        we create a timed event that will put us to paused
        in a few seconds
        """
        if not config.get_by_tabname('send_chat_states', self.general_jid):
            return
        # First, cancel the delay if it already exists, before rescheduling
        # it at a new date
        self.cancel_paused_delay()
        new_event = timed_events.DelayedEvent(4, self.send_chat_state,
                                              'paused')
        self.core.add_timed_event(new_event)
        self.timed_event_paused = new_event

    def cancel_paused_delay(self):
        """
        Remove that event from the list and set it to None.
        Called for example when the input is emptied, or when the message
        is sent
        """
        if self.timed_event_paused is not None:
            self.core.remove_timed_event(self.timed_event_paused)
            self.timed_event_paused = None

    @command_args_parser.raw
    def command_correct(self, line):
        """
        /correct <fixed message>
        """
        if not line:
            self.core.command_help('correct')
            return
        if not self.last_sent_message:
            self.core.information('There is no message to correct.')
            return
        self.command_say(line, correct=True)

    def completion_correct(self, the_input):
        if self.last_sent_message and the_input.get_argument_position() == 1:
            return the_input.auto_completion([self.last_sent_message['body']],
                                             '',
                                             quotify=False)

    @property
    def inactive(self):
        """Whether we should send inactive or active as a chatstate"""
        return self.core.status.show in ('xa', 'away') or\
                (hasattr(self, 'directed_presence') and not self.directed_presence)

    def move_separator(self):
        self.text_win.remove_line_separator()
        self.text_win.add_line_separator(self._text_buffer)
        self.text_win.refresh()
        self.input.refresh()

    def get_conversation_messages(self):
        return self._text_buffer.messages

    def check_scrolled(self):
        if self.text_win.pos != 0:
            self.state = 'scrolled'

    @command_args_parser.raw
    def command_say(self, line, correct=False):
        pass

    def on_line_up(self):
        return self.text_win.scroll_up(1)

    def on_line_down(self):
        return self.text_win.scroll_down(1)

    def on_scroll_up(self):
        return self.text_win.scroll_up(self.text_win.height - 1)

    def on_scroll_down(self):
        return self.text_win.scroll_down(self.text_win.height - 1)

    def on_half_scroll_up(self):
        return self.text_win.scroll_up((self.text_win.height - 1) // 2)

    def on_half_scroll_down(self):
        return self.text_win.scroll_down((self.text_win.height - 1) // 2)

    @refresh_wrapper.always
    def scroll_separator(self):
        self.text_win.scroll_to_separator()
コード例 #5
0
 def setUp(self):
     self.buf = TextBuffer('hello')
コード例 #6
0
class TextBufferTests(unittest.TestCase):
    def setUp(self):
        self.buf = TextBuffer('hello')

    def test_init(self):
        self.assertEqual(len(self.buf.contents), 5)

    def test_append(self):
        self.buf.append(' world!')
        self.assertEqual(self.buf.contents.head.value, 'h')
        self.assertEqual(self.buf.contents.tail.value, '!')
        self.assertEqual(len(self.buf.contents), 12)

    def test_prepend(self):
        self.buf.prepend('I say ')
        self.assertEqual(self.buf.contents.head.value, 'I')
        self.assertEqual(self.buf.contents.tail.value, 'o')
        self.assertEqual(len(self.buf.contents), 11)

    def test_delete_front(self):
        self.buf.append(' world!')
        self.buf.delete_front(6)
        self.assertEqual(self.buf.contents.head.value, 'w')
        self.assertEqual(self.buf.contents.tail.value, '!')
        self.assertEqual(len(self.buf.contents), 6)

    def test_delete_back(self):
        self.buf.append(' there, I am from Lambda School')
        self.buf.delete_back(7)
        self.assertEqual(self.buf.contents.tail.value, 'a')
        self.assertEqual(len(self.buf.contents), 29)

    def test_join_other_buffer(self):
        other_buf = TextBuffer(' world!')
        self.buf.join(other_buf)
        self.assertEqual(self.buf.contents.head.value, 'h')
        self.assertEqual(self.buf.contents.tail.value, '!')
        self.assertEqual(len(self.buf.contents), 12)

    def test_join_string(self):
        string = ' i am a string?'
        self.buf.join_string(string)
        self.assertEqual(self.buf.contents.head.value, 'h')
        self.assertEqual(self.buf.contents.tail.value, '?')
        self.assertEqual(len(self.buf.contents), 20)
コード例 #7
0
 def test_join_other_buffer(self):
     other_buf = TextBuffer(' world!')
     self.buf.join(other_buf)
     self.assertEqual(self.buf.contents.head.value, 'h')
     self.assertEqual(self.buf.contents.tail.value, '!')
     self.assertEqual(len(self.buf.contents), 12)