From e6f857a5367feb2ff2ce536125007165a17c8148 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 11 Sep 2016 10:39:47 +0200 Subject: [PATCH] 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. --- evennia/commands/cmdparser.py | 8 ++++---- evennia/objects/manager.py | 5 ++--- evennia/server/evennia_launcher.py | 6 ++++++ evennia/settings_default.py | 23 ++++++++++++++++++----- evennia/utils/utils.py | 14 +++++++------- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/evennia/commands/cmdparser.py b/evennia/commands/cmdparser.py index 49ecdebb4d..db210b6013 100644 --- a/evennia/commands/cmdparser.py +++ b/evennia/commands/cmdparser.py @@ -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)) diff --git a/evennia/objects/manager.py b/evennia/objects/manager.py index 656d699b3f..d648c50030 100644 --- a/evennia/objects/manager.py +++ b/evennia/objects/manager.py @@ -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: diff --git a/evennia/server/evennia_launcher.py b/evennia/server/evennia_launcher.py index 1a0a1afd57..c29d82e3a0 100644 --- a/evennia/server/evennia_launcher.py +++ b/evennia/server/evennia_launcher.py @@ -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): diff --git a/evennia/settings_default.py b/evennia/settings_default.py index 6a74547e56..8cb0d06628 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -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...) and (?P...) - 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[0-9]+)-(?P.*)" +# 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 diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index f76caa7bfd..3099675e67 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -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