Remove channel nick-replace from inputfunc
This commit is contained in:
parent
3c4578b648
commit
ae9578e1de
4 changed files with 113 additions and 39 deletions
|
|
@ -55,8 +55,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
Talk on and manage in-game channels.
|
Talk on and manage in-game channels.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
channel channelname [= <msg>]
|
|
||||||
channel
|
channel
|
||||||
|
channel channelname [= <msg>]
|
||||||
channel/list
|
channel/list
|
||||||
channel/all
|
channel/all
|
||||||
channel/history channelname [= index]
|
channel/history channelname [= index]
|
||||||
|
|
@ -88,7 +88,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
"create", "destroy", "desc", "lock", "unlock", "boot", "ban", "unban", "who",)
|
"create", "destroy", "desc", "lock", "unlock", "boot", "ban", "unban", "who",)
|
||||||
|
|
||||||
# note - changing this will invalidate existing aliases in db
|
# note - changing this will invalidate existing aliases in db
|
||||||
channel_msg_nick_alias = "{alias} $1"
|
# channel_msg_nick_alias = r"{alias}\s*?(?P<arg1>.+?){{0,1}}"
|
||||||
|
channel_msg_nick_alias = r"{alias} (?P<arg1>.+?)"
|
||||||
channel_msg_nick_replacement = "channel {channelname} = $1"
|
channel_msg_nick_replacement = "channel {channelname} = $1"
|
||||||
|
|
||||||
def search_channel(self, channelname, exact=False):
|
def search_channel(self, channelname, exact=False):
|
||||||
|
|
@ -240,11 +241,13 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
"""
|
"""
|
||||||
chan_key = channel.key.lower()
|
chan_key = channel.key.lower()
|
||||||
msg_alias = self.channel_msg_nick_alias.format(alias=alias)
|
msg_alias = self.channel_msg_nick_alias.format(alias=alias)
|
||||||
|
print("msg_alias", msg_alias)
|
||||||
msg_replacement = self.channel_msg_nick_replacement.format(channelname=chan_key)
|
msg_replacement = self.channel_msg_nick_replacement.format(channelname=chan_key)
|
||||||
|
|
||||||
if chan_key != alias:
|
if chan_key != alias:
|
||||||
self.caller.nicks.add(alias, chan_key, category="channel", **kwargs)
|
self.caller.nicks.add(alias, chan_key, category="channel", **kwargs)
|
||||||
self.caller.nicks.add(msg_alias, msg_replacement, category="channel", **kwargs)
|
self.caller.nicks.add(msg_alias, msg_replacement, category="inputline",
|
||||||
|
regex_pattern=True, **kwargs)
|
||||||
|
|
||||||
def remove_alias(self, alias, **kwargs):
|
def remove_alias(self, alias, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
@ -269,8 +272,9 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
if caller.nicks.get(alias, category="channel", **kwargs):
|
if caller.nicks.get(alias, category="channel", **kwargs):
|
||||||
msg_alias = self.channel_msg_nick_alias.format(alias=alias)
|
msg_alias = self.channel_msg_nick_alias.format(alias=alias)
|
||||||
caller.nicks.remove(alias, category="channel", **kwargs)
|
caller.nicks.remove(alias, category="channel", **kwargs)
|
||||||
caller.nicks.remove(msg_alias, category="channel", **kwargs)
|
caller.nicks.remove(msg_alias, category="inputline", **kwargs)
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
return False, "No such alias was defined."
|
return False, "No such alias was defined."
|
||||||
|
|
||||||
def get_channel_aliases(self, channel):
|
def get_channel_aliases(self, channel):
|
||||||
|
|
@ -724,7 +728,6 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(err)
|
self.msg(err)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
channels = []
|
channels = []
|
||||||
for channel_name in channel_names:
|
for channel_name in channel_names:
|
||||||
# find a channel by fuzzy-matching. This also checks
|
# find a channel by fuzzy-matching. This also checks
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ def text(session, *args, **kwargs):
|
||||||
puppet = session.puppet
|
puppet = session.puppet
|
||||||
if puppet:
|
if puppet:
|
||||||
txt = puppet.nicks.nickreplace(
|
txt = puppet.nicks.nickreplace(
|
||||||
txt, categories=("inputline", "channel"), include_account=True
|
txt, categories=("inputline"), include_account=True
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
txt = session.account.nicks.nickreplace(
|
txt = session.account.nicks.nickreplace(
|
||||||
txt, categories=("inputline", "channel"), include_account=False
|
txt, categories=("inputline"), include_account=False
|
||||||
)
|
)
|
||||||
kwargs.pop("options", None)
|
kwargs.pop("options", None)
|
||||||
cmdhandler(session, txt, callertype="session", session=session, **kwargs)
|
cmdhandler(session, txt, callertype="session", session=session, **kwargs)
|
||||||
|
|
|
||||||
|
|
@ -1291,6 +1291,7 @@ Custom arg markers
|
||||||
$N argument position (1-99)
|
$N argument position (1-99)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
_RE_NICK_RE_ARG = re.compile(r"arg([1-9][0-9]?)")
|
||||||
_RE_NICK_ARG = re.compile(r"\\(\$)([1-9][0-9]?)")
|
_RE_NICK_ARG = re.compile(r"\\(\$)([1-9][0-9]?)")
|
||||||
_RE_NICK_TEMPLATE_ARG = re.compile(r"(\$)([1-9][0-9]?)")
|
_RE_NICK_TEMPLATE_ARG = re.compile(r"(\$)([1-9][0-9]?)")
|
||||||
_RE_NICK_SPACE = re.compile(r"\\ ")
|
_RE_NICK_SPACE = re.compile(r"\\ ")
|
||||||
|
|
@ -1300,45 +1301,59 @@ class NickTemplateInvalid(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def initialize_nick_templates(in_template, out_template):
|
def initialize_nick_templates(pattern, out_template, pattern_is_regex=False):
|
||||||
"""
|
"""
|
||||||
Initialize the nick templates for matching and remapping a string.
|
Initialize the nick templates for matching and remapping a string.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
in_template (str): The template to be used for nick recognition.
|
pattern (str): The pattern to be used for nick recognition. This will
|
||||||
|
be parsed for shell patterns into a regex, unless `pattern_is_regex`
|
||||||
|
is `True`, in which case it must be an already valid regex string. In
|
||||||
|
this case, instead of `$N`, numbered arguments must instead be given
|
||||||
|
as matching groups named as `argN`, such as `(?P<arg1>.+?)`. Such
|
||||||
|
groups can then also be made optional using e.g. `{?P<arg1>.*?}`.
|
||||||
out_template (str): The template to be used to replace the string
|
out_template (str): The template to be used to replace the string
|
||||||
matched by the in_template.
|
matched by the pattern. This can contain `$N` markers and is never
|
||||||
|
parsed into a regex.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
regex (regex): Regex to match against strings
|
regex, template (str): Regex to match against strings and template
|
||||||
template (str): Template with markers ``{arg1}, {arg2}``, etc for
|
with markers ``{arg1}, {arg2}``, etc for replacement using the standard
|
||||||
replacement using the standard .format method.
|
`.format` method.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
evennia.typecalasses.attributes.NickTemplateInvalid: If the in/out
|
evennia.typecalasses.attributes.NickTemplateInvalid: If the in/out
|
||||||
template does not have a matching number of `$args`.
|
template does not have a matching number of `$args`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
in->out-template: `grin $1 -> emote gives a wicked grin to $1.`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# create the regex for in_template
|
# create the regex from the pattern
|
||||||
regex_string = fnmatch.translate(in_template)
|
if pattern_is_regex:
|
||||||
|
# Explicit regex given from the onset - this already contains argN groups
|
||||||
|
pattern_regex_string = pattern + r"\Z"
|
||||||
|
else:
|
||||||
|
# regex generated by parsing shell pattern syntax - convert $N to argN groups
|
||||||
|
pattern_regex_string = fnmatch.translate(pattern)
|
||||||
|
pattern_regex_string = _RE_NICK_SPACE.sub(r"\\s+", pattern_regex_string)
|
||||||
|
pattern_regex_string = _RE_NICK_ARG.sub(
|
||||||
|
lambda m: "(?P<arg%s>.+?)" % m.group(2), pattern_regex_string)
|
||||||
# we must account for a possible line break coming over the wire
|
# we must account for a possible line break coming over the wire
|
||||||
|
pattern_regex_string = pattern_regex_string[:-2] + r"(?:[\n\r]*?)\Z"
|
||||||
|
|
||||||
# NOTE-PYTHON3: fnmatch.translate format changed since Python2
|
# count and compare the args-nums in pattern and replacement for validation
|
||||||
regex_string = regex_string[:-2] + r"(?:[\n\r]*?)\Z"
|
pattern_args = [match.group(1) for match in _RE_NICK_RE_ARG.finditer(pattern_regex_string)]
|
||||||
|
replacement_args = [match.group(2) for match in _RE_NICK_TEMPLATE_ARG.finditer(out_template)]
|
||||||
|
if set(pattern_args) != set(replacement_args):
|
||||||
|
# We don't have the same amount of argN/$N tags in input/output.
|
||||||
|
raise NickTemplateInvalid("Nicks: Both in/out-templates must contain the same $N tags.")
|
||||||
|
|
||||||
# validate the templates
|
# map the replacement to match the arg1 group-names, to make replacement easy
|
||||||
regex_args = [match.group(2) for match in _RE_NICK_ARG.finditer(regex_string)]
|
|
||||||
temp_args = [match.group(2) for match in _RE_NICK_TEMPLATE_ARG.finditer(out_template)]
|
|
||||||
if set(regex_args) != set(temp_args):
|
|
||||||
# We don't have the same $-tags in input/output.
|
|
||||||
raise NickTemplateInvalid
|
|
||||||
|
|
||||||
regex_string = _RE_NICK_SPACE.sub(r"\\s+", regex_string)
|
|
||||||
regex_string = _RE_NICK_ARG.sub(lambda m: "(?P<arg%s>.+?)" % m.group(2), regex_string)
|
|
||||||
template_string = _RE_NICK_TEMPLATE_ARG.sub(lambda m: "{arg%s}" % m.group(2), out_template)
|
template_string = _RE_NICK_TEMPLATE_ARG.sub(lambda m: "{arg%s}" % m.group(2), out_template)
|
||||||
|
|
||||||
return regex_string, template_string
|
return pattern_regex_string, template_string
|
||||||
|
|
||||||
|
|
||||||
def parse_nick_template(string, template_regex, outtemplate):
|
def parse_nick_template(string, template_regex, outtemplate):
|
||||||
|
|
@ -1346,7 +1361,7 @@ def parse_nick_template(string, template_regex, outtemplate):
|
||||||
Parse a text using a template and map it to another template
|
Parse a text using a template and map it to another template
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
string (str): The input string to processj
|
string (str): The input string to process
|
||||||
template_regex (regex): A template regex created with
|
template_regex (regex): A template regex created with
|
||||||
initialize_nick_template.
|
initialize_nick_template.
|
||||||
outtemplate (str): The template to which to map the matches
|
outtemplate (str): The template to which to map the matches
|
||||||
|
|
@ -1408,8 +1423,6 @@ class NickHandler(AttributeHandler):
|
||||||
Returns:
|
Returns:
|
||||||
str or tuple: The nick replacement string or nick tuple.
|
str or tuple: The nick replacement string or nick tuple.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if return_tuple or "return_obj" in kwargs:
|
if return_tuple or "return_obj" in kwargs:
|
||||||
return super().get(key=key, category=category, **kwargs)
|
return super().get(key=key, category=category, **kwargs)
|
||||||
|
|
@ -1423,24 +1436,46 @@ class NickHandler(AttributeHandler):
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def add(self, key, replacement, category="inputline", **kwargs):
|
def add(self, pattern, replacement, category="inputline", pattern_is_regex=False, **kwargs):
|
||||||
"""
|
"""
|
||||||
Add a new nick.
|
Add a new nick, a mapping pattern -> replacement.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): A key (or template) for the nick to match for.
|
pattern (str): A pattern to match for. This will be parsed for
|
||||||
replacement (str): The string (or template) to replace `key` with (the "nickname").
|
shell patterns using the `fnmatch` library and can contain
|
||||||
|
`$N`-markers to indicate the locations of arguments to catch. If
|
||||||
|
`pattern_is_regex=True`, this must instead be a valid regular
|
||||||
|
expression and the `$N`-markers must be named `argN` matching
|
||||||
|
groups (see examples).
|
||||||
|
replacement (str): The string (or template) to replace `key` with
|
||||||
|
(the "nickname"). This may contain `$N` markers to indicate where to
|
||||||
|
place the argument-matches
|
||||||
category (str, optional): the category within which to
|
category (str, optional): the category within which to
|
||||||
retrieve the nick. The "inputline" means replacing data
|
retrieve the nick. The "inputline" means replacing data
|
||||||
sent by the user.
|
sent by the user.
|
||||||
|
pattern_is_regex (bool): If `True`, the `pattern` will be parsed as a
|
||||||
|
raw regex string. Instead of using `$N` markers in this string, one
|
||||||
|
then must mark numbered arguments as a named regex-groupd named `argN`.
|
||||||
|
For example, `(?P<arg1>.+?)` will match the behavior of using `$1`
|
||||||
|
in the shell pattern.
|
||||||
kwargs (any, optional): These are passed on to `AttributeHandler.get`.
|
kwargs (any, optional): These are passed on to `AttributeHandler.get`.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
For most cases, the shell-pattern is much shorter and easier. The
|
||||||
|
regex pattern form can be useful for more complex matchings though,
|
||||||
|
for example in order to add optional arguments, such as with
|
||||||
|
`(?P<argN>.*?)`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- pattern (default shell syntax): `"gr $1 at $2"`
|
||||||
|
- pattern (with pattern_is_regex=True): `r"gr (?P<arg1>.+?) at (?P<arg2>.+?)"
|
||||||
|
- replacement: `"emote With a flourish, $1 grins at $2."`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# if category == "channel":
|
nick_regex, nick_template = initialize_nick_templates(
|
||||||
# nick_regex, nick_template = initialize_nick_templates(key + " $1", replacement + " $1")
|
pattern, replacement, pattern_is_regex=pattern_is_regex)
|
||||||
# else:
|
super().add(pattern, (nick_regex, nick_template, pattern, replacement),
|
||||||
nick_regex, nick_template = initialize_nick_templates(key, replacement)
|
category=category, **kwargs)
|
||||||
super().add(key, (nick_regex, nick_template, key, replacement), category=category, **kwargs)
|
|
||||||
|
|
||||||
def remove(self, key, category="inputline", **kwargs):
|
def remove(self, key, category="inputline", **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ Unit tests for typeclass base system
|
||||||
"""
|
"""
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from evennia.utils.test_resources import EvenniaTest
|
from evennia.utils.test_resources import EvenniaTest
|
||||||
|
from evennia.typeclasses import attributes
|
||||||
from mock import patch
|
from mock import patch
|
||||||
|
from parameterized import parameterized
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# Manager tests
|
# Manager tests
|
||||||
|
|
@ -171,3 +173,37 @@ class TestTags(EvenniaTest):
|
||||||
def test_does_not_have_tag_category_only(self):
|
def test_does_not_have_tag_category_only(self):
|
||||||
self.obj1.tags.add("tagC", "categoryC")
|
self.obj1.tags.add("tagC", "categoryC")
|
||||||
self.assertFalse(self.obj1.tags.has(category="categoryD"))
|
self.assertFalse(self.obj1.tags.has(category="categoryD"))
|
||||||
|
|
||||||
|
|
||||||
|
class TestNickHandler(EvenniaTest):
|
||||||
|
"""
|
||||||
|
Test the nick handler mechanisms.
|
||||||
|
|
||||||
|
"""
|
||||||
|
@parameterized.expand([
|
||||||
|
# ("gr $1 $2 at $3", "emote with a $1 smile, $2 grins at $3.", False,
|
||||||
|
# "gr happy Foo at Bar", "emote with a happy smile, Foo grins at Bar."),
|
||||||
|
# ("gr (?P<arg1>.+?) (?P<arg2>.+?) at (?P<arg3>.+?)",
|
||||||
|
# "emote with a $1 smile, $2 grins at $3.", True,
|
||||||
|
# "gr happy Foo at Bar", "emote with a happy smile, Foo grins at Bar."),
|
||||||
|
("groo $1", "channel groo = $1", True,
|
||||||
|
"groo Hello world", "channel groo = Hello world"),
|
||||||
|
(r"groo\s*?(?P<arg1>.*?)", "channel groo = $1", False,
|
||||||
|
"groo Hello world", "channel groo = Hello world"),
|
||||||
|
(r"groo\s*?(?P<arg1>.*?)", "channel groo = $1", False,
|
||||||
|
"groo ", "channel groo = "),
|
||||||
|
(r"groo\s*?(?P<arg1>.*?)", "channel groo = $1", False,
|
||||||
|
"groo", "channel groo = "),
|
||||||
|
])
|
||||||
|
def test_nick_parsing(self, pattern, replacement, pattern_is_regex,
|
||||||
|
inp_string, expected_replaced):
|
||||||
|
"""
|
||||||
|
Setting up nick patterns and make sure they replace as expected.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.char1.nicks.add(pattern, replacement,
|
||||||
|
category="inputline", pattern_is_regex=pattern_is_regex)
|
||||||
|
actual_replaced = self.char1.nicks.nickreplace(inp_string)
|
||||||
|
|
||||||
|
self.assertEqual(expected_replaced, actual_replaced)
|
||||||
|
self.char1.nicks.clear()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue