Merge remote-tracking branch 'origin/mr/31'

This commit is contained in:
Maxime “pep” Buquet 2019-06-22 03:52:26 +02:00
commit e1ca4ff338
2 changed files with 140 additions and 1 deletions

View file

@ -316,6 +316,11 @@ These commands will work in any conversation tab (MultiUserChat, Private, or
/clear
Clear the current buffer.
/sb
**Usage:** ``/sb end home clear status goto <+|-linecount>|<linenum>|<timestamp>``
Allows to go to the given line or message in the window.
.. _muctab-commands:
MultiUserChat tab commands

View file

@ -26,12 +26,15 @@ from poezio.core.structs import Command, Completion, Status
from poezio import timed_events
from poezio import windows
from poezio import xhtml
from poezio import poopt
from math import ceil, log10
from poezio.windows.funcs import truncate_nick, parse_attrs
from poezio.common import safeJID
from poezio.config import config
from poezio.decorators import refresh_wrapper
from poezio.logger import logger
from poezio.text_buffer import TextBuffer
from poezio.theming import get_theme, dump_tuple
from poezio.theming import to_curses_attr, get_theme, dump_tuple
from poezio.decorators import command_args_parser
log = logging.getLogger(__name__)
@ -490,6 +493,11 @@ class ChatTab(Tab):
self.command_say,
usage='<message>',
shortdesc='Send the message.')
self.register_command(
'sb',
self.command_sb,
usage="end home clear status goto <+|-linecount>|<linenum>|<timestamp>",
shortdesc='Scrollback to the given line number, message, or clear the buffer.')
self.register_command(
'xhtml',
self.command_xhtml,
@ -782,6 +790,132 @@ class ChatTab(Tab):
def command_say(self, line, correct=False):
pass
def goto_build_lines(self, new_date):
text_buffer = self._text_buffer
built_lines = []
message_count = 0
for message in text_buffer.messages:
# Build lines of a message
txt = message.txt
timestamp = config.get('show_timestamps')
nick_size = config.get('max_nick_length')
nick = truncate_nick(message.nickname, nick_size)
offset = 0
theme = get_theme()
if message.ack:
if message.ack > 0:
offset += poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1
else:
offset += poopt.wcswidth(theme.CHAR_NACK) + 1
if nick:
offset += poopt.wcswidth(nick) + 2
if message.revisions > 0:
offset += ceil(log10(message.revisions + 1))
if message.me:
offset += 1
if timestamp:
if message.str_time:
offset += 1 + len(message.str_time)
if theme.CHAR_TIME_LEFT and message.str_time:
offset += 1
if theme.CHAR_TIME_RIGHT and message.str_time:
offset += 1
lines = poopt.cut_text(txt, self.text_win.width - offset - 1)
for line in lines:
built_lines.append(line)
# Find the message with timestamp less than or equal to the queried
# timestamp and goto that location in the tab.
if message.time <= new_date:
message_count += 1
if len(self.text_win.built_lines) - self.text_win.height >= len(built_lines):
self.text_win.pos = len(self.text_win.built_lines) - self.text_win.height - len(built_lines) + 1
else:
self.text_win.pos = 0
if message_count == 0:
self.text_win.scroll_up(len(self.text_win.built_lines))
self.core.refresh_window()
@command_args_parser.quoted(0, 2)
def command_sb(self, args):
"""
/sb clear
/sb home
/sb end
/sb goto <+|-linecount>|<linenum>|<timestamp>
The format of timestamp must be [dd[.mm]-<days ago>] hh:mi[:ss]
"""
if args is None or len(args) == 0:
args = ['end']
if len(args) == 1:
if args[0] == 'end':
self.text_win.scroll_down(len(self.text_win.built_lines))
self.core.refresh_window()
return
elif args[0] == 'home':
self.text_win.scroll_up(len(self.text_win.built_lines))
self.core.refresh_window()
return
elif args[0] == 'clear':
self._text_buffer.messages = []
self.text_win.rebuild_everything(self._text_buffer)
self.core.refresh_window()
return
elif args[0] == 'status':
self.core.information('Total %s lines in this tab.' % len(self.text_win.built_lines), 'Info')
return
elif len(args) == 2 and args[0] == 'goto':
for fmt in ('%d %H:%M', '%d %H:%M:%S', '%d:%m %H:%M', '%d:%m %H:%M:%S', '%H:%M', '%H:%M:%S'):
try:
new_date = datetime.strptime(args[1], fmt)
if 'd' in fmt and 'm' in fmt:
new_date = new_date.replace(year=datetime.now().year)
elif 'd' in fmt:
new_date = new_date.replace(year=datetime.now().year, month=datetime.now().month)
else:
new_date = new_date.replace(year=datetime.now().year, month=datetime.now().month, day=datetime.now().day)
except ValueError:
pass
if args[1].startswith('-'):
# Check if the user is giving argument of type goto <-linecount> or goto [-<days ago>] hh:mi[:ss]
if ' ' in args[1]:
new_args = args[1].split(' ')
new_args[0] = new_args[0].strip('-')
new_date = datetime.now()
if new_args[0].isdigit():
new_date = new_date.replace(day=new_date.day - int(new_args[0]))
for fmt in ('%H:%M', '%H:%M:%S'):
try:
arg_date = datetime.strptime(new_args[1], fmt)
new_date = new_date.replace(hour=arg_date.hour, minute=arg_date.minute, second=arg_date.second)
except ValueError:
pass
else:
scroll_len = args[1].strip('-')
if scroll_len.isdigit():
self.text_win.scroll_down(int(scroll_len))
self.core.refresh_window()
return
elif args[1].startswith('+'):
scroll_len = args[1].strip('+')
if scroll_len.isdigit():
self.text_win.scroll_up(int(scroll_len))
self.core.refresh_window()
return
# Check for the argument of type goto <linenum>
elif args[1].isdigit():
if len(self.text_win.built_lines) - self.text_win.height >= int(args[1]):
self.text_win.pos = len(self.text_win.built_lines) - self.text_win.height - int(args[1])
self.core.refresh_window()
return
else:
self.text_win.pos = 0
self.core.refresh_window()
return
elif args[1] == '0':
args = ['home']
# new_date is the timestamp for which the user has queried.
self.goto_build_lines(new_date)
def on_line_up(self):
return self.text_win.scroll_up(1)