Merge pull request #2794 from InspectorCaracal/rpsystem-fix-selfref
rpsystem: Add special-case handling for self-references.
This commit is contained in:
commit
151d9b1eae
2 changed files with 63 additions and 24 deletions
|
|
@ -202,7 +202,7 @@ _RE_RIGHT_BRACKETS = re.compile(r"\}+", _RE_FLAGS)
|
||||||
_RE_REF = re.compile(r"\{+\#([0-9]+[\^\~tv]{0,1})\}+")
|
_RE_REF = re.compile(r"\{+\#([0-9]+[\^\~tv]{0,1})\}+")
|
||||||
|
|
||||||
# This regex is used to quickly reference one self in an emote.
|
# This regex is used to quickly reference one self in an emote.
|
||||||
_RE_SELF_REF = re.compile(r"/me|@", _RE_FLAGS)
|
_RE_SELF_REF = re.compile(r"(/me|@)(?=\W+)", _RE_FLAGS)
|
||||||
|
|
||||||
# regex for non-alphanumberic end of a string
|
# regex for non-alphanumberic end of a string
|
||||||
_RE_CHAREND = re.compile(r"\W+$", _RE_FLAGS)
|
_RE_CHAREND = re.compile(r"\W+$", _RE_FLAGS)
|
||||||
|
|
@ -235,6 +235,26 @@ class RecogError(Exception):
|
||||||
class LanguageError(Exception):
|
class LanguageError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _get_case_ref(string):
|
||||||
|
"""
|
||||||
|
Helper function which parses capitalization and
|
||||||
|
returns the appropriate case-ref character for emotes.
|
||||||
|
"""
|
||||||
|
# default to retaining the original case
|
||||||
|
case = "~"
|
||||||
|
# internal flags for the case used for the original /query
|
||||||
|
# - t for titled input (like /Name)
|
||||||
|
# - ^ for all upercase input (like /NAME)
|
||||||
|
# - v for lower-case input (like /name)
|
||||||
|
# - ~ for mixed case input (like /nAmE)
|
||||||
|
if string.istitle():
|
||||||
|
case = "t"
|
||||||
|
elif string.isupper():
|
||||||
|
case = "^"
|
||||||
|
elif string.islower():
|
||||||
|
case = "v"
|
||||||
|
|
||||||
|
return case
|
||||||
|
|
||||||
# emoting mechanisms
|
# emoting mechanisms
|
||||||
def parse_language(speaker, emote):
|
def parse_language(speaker, emote):
|
||||||
|
|
@ -339,7 +359,7 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
|
||||||
"""
|
"""
|
||||||
# build a list of candidates with all possible referrable names
|
# build a list of candidates with all possible referrable names
|
||||||
# include 'me' keyword for self-ref
|
# include 'me' keyword for self-ref
|
||||||
candidate_map = [(sender, "me")]
|
candidate_map = []
|
||||||
for obj in candidates:
|
for obj in candidates:
|
||||||
# check if sender has any recogs for obj and add
|
# check if sender has any recogs for obj and add
|
||||||
if hasattr(sender, "recog"):
|
if hasattr(sender, "recog"):
|
||||||
|
|
@ -365,6 +385,15 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
|
||||||
errors = []
|
errors = []
|
||||||
obj = None
|
obj = None
|
||||||
nmatches = 0
|
nmatches = 0
|
||||||
|
# first, find and replace any self-refs
|
||||||
|
for self_match in list(_RE_SELF_REF.finditer(string)):
|
||||||
|
matched = self_match.group()
|
||||||
|
case = _get_case_ref(matched.lstrip(_PREFIX)) if case_sensitive else ""
|
||||||
|
key = f"#{sender.id}{case}"
|
||||||
|
# replaced with ref
|
||||||
|
string = _RE_SELF_REF.sub(f"{{{key}}}", string, count=1)
|
||||||
|
mapping[key] = sender
|
||||||
|
|
||||||
for marker_match in reversed(list(_RE_OBJ_REF_START.finditer(string))):
|
for marker_match in reversed(list(_RE_OBJ_REF_START.finditer(string))):
|
||||||
# we scan backwards so we can replace in-situ without messing
|
# we scan backwards so we can replace in-situ without messing
|
||||||
# up later occurrences. Given a marker match, query from
|
# up later occurrences. Given a marker match, query from
|
||||||
|
|
@ -456,24 +485,9 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
|
||||||
errors.append(_EMOTE_NOMATCH_ERROR.format(ref=marker_match.group()))
|
errors.append(_EMOTE_NOMATCH_ERROR.format(ref=marker_match.group()))
|
||||||
elif nmatches == 1:
|
elif nmatches == 1:
|
||||||
# a unique match - parse into intermediary representation
|
# a unique match - parse into intermediary representation
|
||||||
case = "~" # retain original case of sdesc
|
case = _get_case_ref(marker_match.group()) if case_sensitive else ""
|
||||||
if case_sensitive:
|
|
||||||
# case sensitive mode
|
|
||||||
# internal flags for the case used for the original /query
|
|
||||||
# - t for titled input (like /Name)
|
|
||||||
# - ^ for all upercase input (like /NAME)
|
|
||||||
# - v for lower-case input (like /name)
|
|
||||||
# - ~ for mixed case input (like /nAmE)
|
|
||||||
matchtext = marker_match.group().lstrip(_PREFIX)
|
|
||||||
if matchtext.istitle():
|
|
||||||
case = "t"
|
|
||||||
elif matchtext.isupper():
|
|
||||||
case = "^"
|
|
||||||
elif matchtext.islower():
|
|
||||||
case = "v"
|
|
||||||
|
|
||||||
key = f"#{obj.id}{case}"
|
|
||||||
# recombine emote with matched text replaced by ref
|
# recombine emote with matched text replaced by ref
|
||||||
|
key = f"#{obj.id}{case}"
|
||||||
string = f"{head}{{{key}}}{tail}"
|
string = f"{head}{{{key}}}{tail}"
|
||||||
mapping[key] = obj
|
mapping[key] = obj
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ recog02 = "Mr Receiver2"
|
||||||
recog10 = "Mr Sender"
|
recog10 = "Mr Sender"
|
||||||
emote = 'With a flair, /me looks at /first and /colliding sdesc-guy. She says "This is a test."'
|
emote = 'With a flair, /me looks at /first and /colliding sdesc-guy. She says "This is a test."'
|
||||||
case_emote = "/Me looks at /first. Then, /me looks at /FIRST, /First and /Colliding twice."
|
case_emote = "/Me looks at /first. Then, /me looks at /FIRST, /First and /Colliding twice."
|
||||||
|
poss_emote = "/Me frowns at /first for trying to steal /me's test."
|
||||||
|
|
||||||
|
|
||||||
class TestRPSystem(BaseEvenniaTest):
|
class TestRPSystem(BaseEvenniaTest):
|
||||||
|
|
@ -140,18 +141,21 @@ class TestRPSystem(BaseEvenniaTest):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def parse_sdescs_and_recogs(self):
|
def test_parse_sdescs_and_recogs(self):
|
||||||
speaker = self.speaker
|
speaker = self.speaker
|
||||||
speaker.sdesc.add(sdesc0)
|
speaker.sdesc.add(sdesc0)
|
||||||
self.receiver1.sdesc.add(sdesc1)
|
self.receiver1.sdesc.add(sdesc1)
|
||||||
self.receiver2.sdesc.add(sdesc2)
|
self.receiver2.sdesc.add(sdesc2)
|
||||||
|
id0 = f"#{speaker.id}"
|
||||||
|
id1 = f"#{self.receiver1.id}"
|
||||||
|
id2 = f"#{self.receiver2.id}"
|
||||||
candidates = (self.receiver1, self.receiver2)
|
candidates = (self.receiver1, self.receiver2)
|
||||||
result = (
|
result = (
|
||||||
'With a flair, {#9} looks at {#10} and {#11}. She says "This is a test."',
|
'With a flair, {'+id0+'} looks at {'+id1+'} and {'+id2+'}. She says "This is a test."',
|
||||||
{
|
{
|
||||||
"#11": "Another nice colliding sdesc-guy for tests",
|
id2: self.receiver2,
|
||||||
"#10": "The first receiver of emotes.",
|
id1: self.receiver1,
|
||||||
"#9": "A nice sender of emotes",
|
id0: speaker,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|
@ -164,6 +168,27 @@ class TestRPSystem(BaseEvenniaTest):
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_possessive_selfref(self):
|
||||||
|
speaker = self.speaker
|
||||||
|
speaker.sdesc.add(sdesc0)
|
||||||
|
self.receiver1.sdesc.add(sdesc1)
|
||||||
|
self.receiver2.sdesc.add(sdesc2)
|
||||||
|
id0 = f"#{speaker.id}"
|
||||||
|
id1 = f"#{self.receiver1.id}"
|
||||||
|
id2 = f"#{self.receiver2.id}"
|
||||||
|
candidates = (self.receiver1, self.receiver2)
|
||||||
|
result = (
|
||||||
|
"{"+id0+"} frowns at {"+id1+"} for trying to steal {"+id0+"}'s test.",
|
||||||
|
{
|
||||||
|
id1: self.receiver1,
|
||||||
|
id0: speaker,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
rpsystem.parse_sdescs_and_recogs(speaker, candidates, poss_emote, case_sensitive=False),
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_sdesc(self):
|
def test_get_sdesc(self):
|
||||||
looker = self.speaker # Sender
|
looker = self.speaker # Sender
|
||||||
target = self.receiver1 # Receiver1
|
target = self.receiver1 # Receiver1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue