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 collections
import collections.abc
import textwrap
try:
import ircmatch
@ -384,7 +385,7 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
"""
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
is optional, and defaults to the main PyLink client if not specified."""
if not text:
@ -395,6 +396,7 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
return
source = source or self.pseudoclient.uid
def _msg(text):
if notice:
self.notice(source, target, text)
cmd = 'PYLINK_SELF_NOTICE'
@ -402,13 +404,20 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
self.message(source, target, text)
cmd = 'PYLINK_SELF_PRIVMSG'
if loopback:
# Determines whether we should send a hook for this msg(), to relay things like services
# Determines whether we should send a hook for this msg(), to forward things like services
# replies across relay.
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,
loopback=True):
loopback=True, wrap=True):
"""
Core of the reply() function - replies to the last caller in the right context
(channel or PM).
@ -428,7 +437,7 @@ class PyLinkNetworkCore(structures.CamelCaseToSnakeCase):
else:
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):
"""
@ -1445,6 +1454,14 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
return sname
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
class IRCNetwork(PyLinkNetworkCoreWithUtils):
@ -1844,6 +1861,21 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
self._socket.shutdown(socket.SHUT_WR)
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
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:
irc.reply('Suppressing %s more line(s) of output.' % (len(lines) - PPRINT_MAX_LINES))
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')

View File

@ -479,6 +479,7 @@ class ServiceBot():
if command not in self.commands:
_reply('Error: Unknown command %r.' % command)
return
else:
funcs = self.commands[command]
if len(funcs) > 1:
@ -500,8 +501,8 @@ class ServiceBot():
# 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
# code without affecting the output on IRC.
# TODO: we should probably verify that the output line doesn't exceed IRC
# line length limits...
# (On the same topic, real line wrapping on IRC is done in irc.msg() as of
# 2.0-alpha4)
next_line = ''
for linenum, line in enumerate(lines[1:], 1):
stripped_line = line.strip()
@ -522,6 +523,7 @@ class ServiceBot():
_reply_format(next_line)
next_line = '' # Reset the next line buffer
else:
# Show the last line.
_reply_format(next_line)
else:
_reply("Error: Command %r doesn't offer any help." % command)