3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-01 01:09:22 +01:00

core: implement text wrapping in irc.msg()

Closes #153.
This commit is contained in:
James Lu 2018-05-11 14:38:21 -07:00
parent 5d098f57d7
commit 0ac5d424d8
3 changed files with 51 additions and 15 deletions

View File

@ -20,6 +20,7 @@ import string
import re import re
import collections import collections
import collections.abc import collections.abc
import textwrap
try: try:
import ircmatch import ircmatch
@ -384,7 +385,7 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
""" """
world.services['pylink'].call_cmd(self, source, text) world.services['pylink'].call_cmd(self, source, text)
def msg(self, target, text, notice=None, source=None, loopback=True): def msg(self, target, text, notice=None, source=None, loopback=True, wrap=True):
"""Handy function to send messages/notices to clients. Source """Handy function to send messages/notices to clients. Source
is optional, and defaults to the main PyLink client if not specified.""" is optional, and defaults to the main PyLink client if not specified."""
if not text: if not text:
@ -395,20 +396,28 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
return return
source = source or self.pseudoclient.uid source = source or self.pseudoclient.uid
if notice: def _msg(text):
self.notice(source, target, text) if notice:
cmd = 'PYLINK_SELF_NOTICE' self.notice(source, target, text)
else: cmd = 'PYLINK_SELF_NOTICE'
self.message(source, target, text) else:
cmd = 'PYLINK_SELF_PRIVMSG' self.message(source, target, text)
cmd = 'PYLINK_SELF_PRIVMSG'
if loopback: # Determines whether we should send a hook for this msg(), to forward things like services
# Determines whether we should send a hook for this msg(), to relay things like services
# replies across relay. # replies across relay.
self.call_hooks([source, cmd, {'target': target, 'text': text}]) if loopback:
self.call_hooks([source, cmd, {'target': target, 'text': text}])
# Optionally wrap the text output.
if wrap:
for line in self.wrap_message(source, target, text):
_msg(line)
else:
_msg(text)
def _reply(self, text, notice=None, source=None, private=None, force_privmsg_in_private=False, def _reply(self, text, notice=None, source=None, private=None, force_privmsg_in_private=False,
loopback=True): loopback=True, wrap=True):
""" """
Core of the reply() function - replies to the last caller in the right context Core of the reply() function - replies to the last caller in the right context
(channel or PM). (channel or PM).
@ -428,7 +437,7 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
else: else:
target = self.called_in target = self.called_in
self.msg(target, text, notice=notice, source=source, loopback=loopback) self.msg(target, text, notice=notice, source=source, loopback=loopback, wrap=wrap)
def reply(self, *args, **kwargs): def reply(self, *args, **kwargs):
""" """
@ -1445,6 +1454,14 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
return sname return sname
return uid # Regular UID, no change return uid # Regular UID, no change
def wrap_message(self, source, target, command, text):
"""
Wraps the given message text into multiple lines (length depends on how much the protocol
allows), and returns these as a list.
"""
# This is protocol specific, so stub it here in the base class.
raise NotImplementedError
utils._proto_utils_class = PyLinkNetworkCoreWithUtils # Used by compatibility wrappers utils._proto_utils_class = PyLinkNetworkCoreWithUtils # Used by compatibility wrappers
class IRCNetwork(PyLinkNetworkCoreWithUtils): class IRCNetwork(PyLinkNetworkCoreWithUtils):
@ -1844,6 +1861,21 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
self._socket.shutdown(socket.SHUT_WR) self._socket.shutdown(socket.SHUT_WR)
self._aborted_send.set() self._aborted_send.set()
def wrap_message(self, source, target, text):
"""
Wraps the given message text into multiple lines, and returns these as a list.
For IRC, the maximum length of one message is calculated as S2S_BUFSIZE (default to 510)
minus the length of ":sender-nick!sender-user@sender-host PRIVMSG #target :"
"""
prefixstr = ":%s PRIVMSG %s :" % (self.get_hostmask(source), target)
maxlen = self.S2S_BUFSIZE - len(prefixstr)
log.debug('(%s) wrap_message: length of prefix %r is %s, S2S_BUFSIZE=%s, maxlen=%s',
self.name, prefixstr, len(prefixstr), self.S2S_BUFSIZE, maxlen)
return textwrap.wrap(text, width=maxlen)
Irc = IRCNetwork Irc = IRCNetwork
class Server(): class Server():

View File

@ -97,7 +97,9 @@ def _eval(irc, source, args, locals_dict=None, pretty_print=False):
if len(lines) > PPRINT_MAX_LINES: if len(lines) > PPRINT_MAX_LINES:
irc.reply('Suppressing %s more line(s) of output.' % (len(lines) - PPRINT_MAX_LINES)) irc.reply('Suppressing %s more line(s) of output.' % (len(lines) - PPRINT_MAX_LINES))
else: else:
irc.reply(repr(result)) # Purposely disable text wrapping so results are cut instead of potentially flooding;
# 'peval' is specifically designed to work around that.
irc.reply(repr(result), wrap=False)
utils.add_cmd(_eval, 'eval') utils.add_cmd(_eval, 'eval')

View File

@ -479,6 +479,7 @@ class ServiceBot():
if command not in self.commands: if command not in self.commands:
_reply('Error: Unknown command %r.' % command) _reply('Error: Unknown command %r.' % command)
return return
else: else:
funcs = self.commands[command] funcs = self.commands[command]
if len(funcs) > 1: if len(funcs) > 1:
@ -500,8 +501,8 @@ class ServiceBot():
# combinations of more) have the effect of showing a new line on IRC. # combinations of more) have the effect of showing a new line on IRC.
# Single newlines are stripped so that word wrap can be applied in source # Single newlines are stripped so that word wrap can be applied in source
# code without affecting the output on IRC. # code without affecting the output on IRC.
# TODO: we should probably verify that the output line doesn't exceed IRC # (On the same topic, real line wrapping on IRC is done in irc.msg() as of
# line length limits... # 2.0-alpha4)
next_line = '' next_line = ''
for linenum, line in enumerate(lines[1:], 1): for linenum, line in enumerate(lines[1:], 1):
stripped_line = line.strip() stripped_line = line.strip()
@ -522,6 +523,7 @@ class ServiceBot():
_reply_format(next_line) _reply_format(next_line)
next_line = '' # Reset the next line buffer next_line = '' # Reset the next line buffer
else: else:
# Show the last line.
_reply_format(next_line) _reply_format(next_line)
else: else:
_reply("Error: Command %r doesn't offer any help." % command) _reply("Error: Command %r doesn't offer any help." % command)