summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2011-03-09 04:56:53 +0100
committerFlorent Le Coz <louiz@louiz.org>2011-03-09 04:56:53 +0100
commita516e78bcf76f07545310332290b6c5443d437a7 (patch)
treea6935bf25d6ff2344efc546fa8c4aed48693620e
parent1a2252b3e5f902eea19b5f295812c9f9a0686815 (diff)
downloadpoezio-a516e78bcf76f07545310332290b6c5443d437a7.tar.gz
poezio-a516e78bcf76f07545310332290b6c5443d437a7.tar.bz2
poezio-a516e78bcf76f07545310332290b6c5443d437a7.tar.xz
poezio-a516e78bcf76f07545310332290b6c5443d437a7.zip
Some optimizations in build_new_message. Also cleaned up. Added an optimized way to do "wcswidth(string) > n": wcsislonger. And should use less memory because the dict replacing Message and Lines object stores ONLY the needed attributes.
-rw-r--r--src/message.py85
-rw-r--r--src/room.py13
-rw-r--r--src/tabs.py2
-rw-r--r--src/text_buffer.py11
-rw-r--r--src/wcwidth.py16
-rw-r--r--src/windows.py102
6 files changed, 79 insertions, 150 deletions
diff --git a/src/message.py b/src/message.py
deleted file mode 100644
index 004111d7..00000000
--- a/src/message.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright 2010-2011 Le Coz Florent <louiz@louiz.org>
-#
-# This file is part of Poezio.
-#
-# Poezio is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# Poezio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
-
-"""
-Define the Message class
-"""
-
-from datetime import datetime
-
-class Message(object):
- """
- A message with all the associated data (nickname, time, color, etc)
- The color can be a single number OR a list of numbers, for
- specials cases like join or quit messages.
- """
- def __init__(self, txt, time=None, nickname=None, nick_color=None, color=None, colorized=False, user=None):
- """
- time is a datetime object, None means 'now'.
- If no nickname is specified, it's an information.
- """
- self.txt = txt
- self.nickname = nickname
- self.time = time
- self.nick_color = nick_color
- self.color = color
- self.colorized = colorized
- self.user = user
-
- def __repr__(self):
- return "<Message txt=%s, nickname=%s, time=%s, user=%s, colorized=%s>" % (self.txt, self.nickname, str(self.time), str(self.user), self.colorized)
-
- def __str__(self):
- return self.__repr__()
-
-class Line(object):
- """
- A line, corresponding to ONE row of a TextWin.
- A message is composed of ONE line or MORE.
- The same particularity for colors in Message class applies
- here too.
- Example:
-
- Text area limit text area limit
- v v
- |[12:12:01] nickone has just joined the room named |
- | test@kikoo.louiz.org |
- |[12:12:23] nickone> hello good morning everyone, I am|
- | seeking for informations about |
- | poezio |
- |[12:12:35] secondnick> Hello nickone, you can get |
- | informations here :\n |
- | http://blablablabla |
-
- To get this result, the three messages should be converted to:
-
- Line(None, None, Datetime(12, 12, 01), "nickone has just joined the room named", 0, 10)
- Line(None, None, None, "test@kikoo.louiz.org", 0, 10)
- Line("nickone", 1, Datetime(12, 12, 23), "hello good morning everyone, I am", 0, 20)
- Line(None, None, None, "seeking for informations about", 0, 20)
- Line(None, None, None, "poezio", 0, 20)
- Line("secondnick", 2, Datetime(12, 12, 35), "Hello nickone, you can get", 0, 23)
- Line(None, None, None, "informations here:", 0, 23)
- Line(None, None, None, "http://blablablabla", 0, 23)
- """
- def __init__(self, nickname, nickname_color, time, text, text_color, text_offset, colorized=False):
- self.nickname = nickname
- self.nickname_color = nickname_color
- self.time = time
- self.text = text
- self.text_color = text_color
- self.text_offset = text_offset
- self.colorized = colorized
diff --git a/src/room.py b/src/room.py
index df97c638..99674aa0 100644
--- a/src/room.py
+++ b/src/room.py
@@ -19,7 +19,6 @@ from datetime import datetime
from random import randrange
from config import config
from logger import logger
-from message import Message
import common
import theme
@@ -114,7 +113,17 @@ class Room(TextBuffer):
color = theme.COLOR_INFORMATION_TEXT
time = time if time is not None else datetime.now()
nick_color = nick_color or user.color if user else None
- message = Message(txt, time, nickname, nick_color, color, colorized, user=user)
+ message = {'txt': txt, 'colorized':colorized,
+ 'time':time}
+ if nickname:
+ message['nickname'] = nickname
+ if nick_color:
+ message['nick_color'] = nick_color
+ if color:
+ message['color'] = color
+ if user:
+ message['user'] = user
+ # message = Message(txt, time, nickname, nick_color, color, colorized, user=user)
while len(self.messages) > self.messages_nb_limit:
self.messages.pop(0)
self.messages.append(message)
diff --git a/src/tabs.py b/src/tabs.py
index ac485d6c..7270208b 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -781,7 +781,7 @@ class MucTab(ChatTab):
user.change_nick(new_nick)
room.add_message(_('"[%(old)s]" is now known as "[%(new)s]"') % {'old':from_nick.replace('"', '\\"'), 'new':new_nick.replace('"', '\\"')}, colorized=True)
# rename the private tabs if needed
- self.core.rename_private_tab(room.name, from_nick, new_nick)
+ self.core.rename_private_tabs(room.name, from_nick, new_nick)
def on_user_banned(self, room, presence, user, from_nick):
"""
diff --git a/src/text_buffer.py b/src/text_buffer.py
index 3b2ddd1a..06847f28 100644
--- a/src/text_buffer.py
+++ b/src/text_buffer.py
@@ -21,7 +21,6 @@ Define the TextBuffer class
import logging
log = logging.getLogger(__name__)
-from message import Message
from datetime import datetime
import theme
from config import config
@@ -44,8 +43,14 @@ class TextBuffer(object):
def add_message(self, txt, time=None, nickname=None, colorized=False, nick_color=None):
color = theme.COLOR_NORMAL_TEXT if nickname is not None else theme.COLOR_INFORMATION_TEXT
nick_color = nick_color
- time = time or datetime.now()
- msg = Message(txt, time, nickname, nick_color, color, colorized)
+ msg = {'txt': txt, 'colorized':colorized,
+ 'time':time or datetime.now()}
+ if nickname:
+ message['nickname'] = nickname
+ if nick_color:
+ message['nick_color'] = nick_color
+ if color:
+ message['color'] = color
self.messages.append(msg)
while len(self.messages) > self.messages_nb_limit:
self.messages.pop(0)
diff --git a/src/wcwidth.py b/src/wcwidth.py
index b72c3ca3..bb0c456e 100644
--- a/src/wcwidth.py
+++ b/src/wcwidth.py
@@ -233,6 +233,22 @@ def wcswidth(s):
width += w
return width
+def wcsislonger(s, l):
+ """
+ Returns the same result than "wcswidth(s) > l" but
+ is faster.
+ """
+ width = 0
+ for c in s:
+ w = wcwidth(c)
+ if w < 0:
+ return -1
+ else:
+ width += w
+ if width > l:
+ return True
+ return False
+
def widthcut(s, m):
"""
Return the first characters of s that can be contained in
diff --git a/src/windows.py b/src/windows.py
index 7ad382d3..316dd6d5 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -38,7 +38,7 @@ from threading import Lock
from contact import Contact, Resource
from roster import RosterGroup, roster
-from message import Line
+# from message import Line
from tabs import MIN_WIDTH, MIN_HEIGHT
from sleekxmpp.xmlstream.stanzabase import JID
@@ -495,67 +495,57 @@ class TextWin(Win):
Return the number of lines that are built for the given
message.
"""
- if message == None: # line separator
+ def cut_text(text, width):
+ """
+ returns the text that should be displayed on the line, and the rest
+ of the text, in a tuple
+ """
+ cutted = wcwidth.widthcut(text, width) or text[:width]
+ limit = cutted.find('\n')
+ if limit >= 0:
+ return (text[limit+1:], text[:limit])
+ if not wcwidth.wcsislonger(text, width):
+ return ('', text)
+ limit = cutted.rfind(' ')
+ if limit <= 0:
+ return (text[len(cutted):], cutted)
+ else:
+ return (text[limit+1:], text[:limit])
+
+ if message is None: # line separator
self.built_lines.append(None)
return 0
- txt = message.txt
+ txt = message.get('txt')
if not txt:
return 0
else:
txt = txt.replace('\t', ' ')
# length of the time
offset = 9+len(theme.CHAR_TIME_LEFT[:1])+len(theme.CHAR_TIME_RIGHT[:1])
- if message.nickname and wcwidth.wcswidth(message.nickname) >= 25:
- nick = message.nickname[:25]+'…'
+ nickname = message.get('nickname')
+ if nickname and len(nickname) >= 25:
+ nick = nickname[:25]+'…'
else:
- nick = message.nickname
+ nick = nickname
if nick:
offset += wcwidth.wcswidth(nick) + 2 # + nick + spaces length
first = True
- this_line_was_broken_by_space = False
nb = 0
while txt != '':
- cutted_txt = wcwidth.widthcut(txt, self.width-offset) or txt[:self.width-offset]
- limit = cutted_txt.find('\n')
- if limit < 0:
- # break between words if possible
- if wcwidth.wcswidth(txt) >= self.width-offset:
- cutted_txt = wcwidth.widthcut(txt, self.width-offset) or txt[:self.width-offset]
- limit = cutted_txt.rfind(' ')
- this_line_was_broken_by_space = True
- if limit <= 0:
- limit = self.width-offset
- this_line_was_broken_by_space = False
- else:
- limit = self.width-offset-1
- this_line_was_broken_by_space = False
- color = message.user.color if message.user else message.nick_color
- if not first:
- nick = None
- time = None
- else: # strftime is VERY slow, improve performance
- # by calling it only one time here, and
- # not at each refresh
- time = {'hour': '%s'%(message.time.strftime("%H"),),
- 'minute': '%s'%(message.time.strftime("%M"),),
- 'second': '%s'%(message.time.strftime("%S"),),
- }
- l = Line(nick, color,
- time,
- wcwidth.widthcut(txt, limit) or txt[:limit], message.color,
- offset,
- message.colorized)
+ (txt, cutted_txt) = cut_text(txt, self.width-offset)
+ l = {'colorized': message.get('colorized'),
+ 'text_offset':offset,
+ 'text_color':message.get('color'),
+ 'text': cutted_txt
+ }
+ color = message.get('user').color if message.get('user') else message.get('nick_color')
+ if first and color:
+ l['nickname_color'] = color
+ if first:
+ l['time'] = message.get('time').strftime("%H:%M:%S")
+ l['nickname'] = nick
self.built_lines.append(l)
nb += 1
- if this_line_was_broken_by_space:
- limit += 1 # jump the space at the start of the line
- cutted_txt = wcwidth.widthcut(txt, limit)
- if not cutted_txt:
- txt = txt[limit:]
- else:
- txt = txt[len(cutted_txt):]
- if txt.startswith('\n'):
- txt = txt[1:]
first = False
while len(self.built_lines) > self.lines_nb_limit:
self.built_lines.pop(0)
@@ -579,12 +569,12 @@ class TextWin(Win):
if line is None:
self.write_line_separator()
else:
- if line.time:
- self.write_time(line.time)
- if line.nickname:
- self.write_nickname(line.nickname, line.nickname_color)
- self.write_text(y, line.text_offset, line.text, line.text_color, line.colorized)
- if y != self.height-1 or (not line or line.text_offset+wcwidth.wcswidth(line.text) < self.width):
+ if line.get('time'):
+ self.write_time(line.get('time'))
+ if line.get('nickname'):
+ self.write_nickname(line.get('nickname'), line.get('nickname_color'))
+ self.write_text(y, line.get('text_offset'), line.get('text'), line.get('text_color'), line.get('colorized'))
+ if y != self.height-1 or (not line or line.get('text_offset')+wcwidth.wcswidth(line.get('text')) < self.width):
self.addstr('\n')
self._refresh()
@@ -648,13 +638,7 @@ class TextWin(Win):
"""
Write the date on the yth line of the window
"""
- self.addstr(theme.CHAR_TIME_LEFT, common.curses_color_pair(theme.COLOR_TIME_LIMITER))
- self.addstr(time['hour'], common.curses_color_pair(theme.COLOR_TIME_NUMBERS))
- self.addstr(':', common.curses_color_pair(theme.COLOR_TIME_SEPARATOR))
- self.addstr(time['minute'], common.curses_color_pair(theme.COLOR_TIME_NUMBERS))
- self.addstr(':', common.curses_color_pair(theme.COLOR_TIME_SEPARATOR))
- self.addstr(time['second'], common.curses_color_pair(theme.COLOR_TIME_NUMBERS))
- self.addstr(theme.CHAR_TIME_RIGHT, common.curses_color_pair(theme.COLOR_TIME_LIMITER))
+ self.addstr(time)
self.addstr(' ')
def resize(self, height, width, y, x, room=None):