Remove setting.SEARCH_MULTIMATCH_SEPARATOR, replacing it with SEARCH_MULTIMATCH_REGEX and SEARCH_MULTIMATCH_TEMPLATE. This allows simple yet powerful control over the error output without needing to overload the parser.

This commit is contained in:
Griatch 2016-09-11 10:39:47 +02:00
parent ad8d105795
commit e6f857a536
5 changed files with 37 additions and 19 deletions

View file

@ -11,8 +11,7 @@ import re
from django.conf import settings
from evennia.utils.logger import log_trace
_MULTIMATCH_SEPARATOR = settings.SEARCH_MULTIMATCH_SEPARATOR
_MULTIMATCH_REGEX = re.compile(r"([0-9]+)%s(.*)" % _MULTIMATCH_SEPARATOR, re.I + re.U)
_MULTIMATCH_REGEX = re.compile(settings.SEARCH_MULTIMATCH_REGEX, re.I + re.U)
def cmdparser(raw_string, cmdset, caller, match_index=None):
"""
@ -92,8 +91,9 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
num_ref_match = _MULTIMATCH_REGEX.match(raw_string)
if num_ref_match:
# the user might be trying to identify the command
# with a #num-command style syntax.
mindex, new_raw_string = num_ref_match.groups()
# with a #num-command style syntax. We expect the regex to
# contain the groups "number" and "name".
mindex, new_raw_string = num_ref_match.group("number"), num_ref_match.group("name")
return cmdparser(new_raw_string, cmdset,
caller, match_index=int(mindex))

View file

@ -17,8 +17,7 @@ _GA = object.__getattribute__
# delayed import
_ATTR = None
_MULTIMATCH_REGEX = re.compile(r"([0-9]+)%s(.*)" %
settings.SEARCH_MULTIMATCH_SEPARATOR, re.I + re.U)
_MULTIMATCH_REGEX = re.compile(settings.SEARCH_MULTIMATCH_REGEX, re.I + re.U)
# Try to use a custom way to parse id-tagged multimatches.
@ -389,7 +388,7 @@ class ObjectDBManager(TypedObjectManager):
match_number = None
if match:
# strips the number
match_number, searchdata = match.groups()
match_number, searchdata = match.group("number"), match.group("name")
match_number = int(match_number) - 1
match_number = match_number if match_number >= 0 else None
if match_number is not None or not exact:

View file

@ -791,6 +791,12 @@ def error_check_python_modules():
raise DeprecationWarning(deprstring % "PLAYER_TYPECLASS_PATHS")
if hasattr(settings, "CHANNEL_TYPECLASS_PATHS"):
raise DeprecationWarning(deprstring % "CHANNEL_TYPECLASS_PATHS")
if hasattr(settings, "SEARCH_MULTIMATCH_SEPARATOR"):
raise DeprecationWarning(
"settings.SEARCH_MULTIMATCH_SEPARATOR was replaced by "
"SEARCH_MULTIMATCH_REGEX and SEARCH_MULTIMATCH_TEMPLATE. "
"Update your settings file (see evennia/settings_default.py "
"for more info).")
from evennia.commands import cmdsethandler
if not cmdsethandler.import_cmdset(settings.CMDSET_UNLOGGEDIN, None):

View file

@ -249,13 +249,26 @@ CONN_MAX_AGE = 3600 * 7
COMMAND_PARSER = "evennia.commands.cmdparser.cmdparser"
# On a multi-match when search objects or commands, the user has the
# ability to search again with an index marker that differentiates
# the results. If multiple "box" objects are found, they can by
# default use 1-box, 2-box etc to refine the search. Below you
# can change the index separator character used.
SEARCH_MULTIMATCH_SEPARATOR = '-'
# the results. If multiple "box" objects
# are found, they can by default be separated as 1-box, 2-box. Below you
# can change the regular expression used. The regex must have one
# have two capturing groups (?P<prefix>...) and (?P<name>...) - the default
# parser expects this. It should
# also involve a number starting from 1. When changing this you must also
# update SEARCH_MULTIMATCH_TEMPLATE to properly describe the syntax.
SEARCH_MULTIMATCH_REGEX = r"(?P<number>[0-9]+)-(?P<name>.*)"
# To display multimatch errors we must display each multimatch in a way that
# instructs users to separate their multimatches in a way SEARCH_MULTIMATCH_REGEX
# above understands; for example by making sure they must write 1-box, 2-box etc.
# The template must contain {number} - a number to separate multi-matches, starting
# from 1; {name} - the name of the multimatched entity; {aliases} - eventual
# aliases for the entity; {info} - extra info like #dbrefs for staff. Don't
# forget a line break if you want one match per line.
SEARCH_MULTIMATCH_TEMPLATE = " {number}-{name}{aliases}{info}\n"
# The handler that outputs errors when using any API-level search
# (not manager methods). This function should correctly report errors
# both for command- and object-searches.
# both for command- and object-searches. This allows full control
# over the error output (it uses SEARCH_MULTIMATCH_TEMPLATE by default).
SEARCH_AT_RESULT = "evennia.utils.utils.at_search_result"
# The module holding text strings for the connection screen.
# This module should contain one or more variables

View file

@ -28,7 +28,7 @@ from django.utils import timezone
from django.utils.translation import ugettext as _
from evennia.utils import logger
_MULTIMATCH_SEPARATOR = settings.SEARCH_MULTIMATCH_SEPARATOR
_MULTIMATCH_TEMPLATE = settings.SEARCH_MULTIMATCH_TEMPLATE
_EVENNIA_DIR = settings.EVENNIA_DIR
_GAME_DIR = settings.GAME_DIR
@ -1712,15 +1712,15 @@ def at_search_result(matches, caller, query="", quiet=False, **kwargs):
matches = None
elif len(matches) > 1:
error = kwargs.get("multimatch_string") or \
_("More than one match for '%s' (please narrow target):" % query)
_("More than one match for '%s' (please narrow target):\n" % query)
for num, result in enumerate(matches):
# we need to consider Commands, where .aliases is a list
aliases = result.aliases.all() if hasattr(result.aliases, "all") else result.aliases
error += "\n %i%s%s%s%s" % (
num + 1, _MULTIMATCH_SEPARATOR,
result.get_display_name(caller) if hasattr(result, "get_display_name") else query,
" [%s]" % ";".join(aliases) if aliases else "",
result.get_extra_info(caller))
error += _MULTIMATCH_TEMPLATE.format(
number=num + 1,
name=result.get_display_name(caller) if hasattr(result, "get_display_name") else query,
aliases=" [%s]" % ";".join(aliases) if aliases else "",
info=result.get_extra_info(caller))
matches = None
else:
# exactly one match