Merge branch 'master' into develop
This commit is contained in:
commit
a8891b44a6
9 changed files with 189 additions and 135 deletions
|
|
@ -417,7 +417,7 @@ class CmdSay(COMMAND_DEFAULT_CLASS):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Call the at_after_say hook on the character
|
# Call the at_after_say hook on the character
|
||||||
caller.at_say(speech)
|
caller.at_say(speech, msg_self=True)
|
||||||
|
|
||||||
|
|
||||||
class CmdWhisper(COMMAND_DEFAULT_CLASS):
|
class CmdWhisper(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
@ -425,10 +425,11 @@ class CmdWhisper(COMMAND_DEFAULT_CLASS):
|
||||||
Speak privately as your character to another
|
Speak privately as your character to another
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
whisper <player> = <message>
|
whisper <character> = <message>
|
||||||
|
whisper <char1>, <char2> = <message?
|
||||||
|
|
||||||
Talk privately to those in your current location, without
|
Talk privately to one or more characters in your current location, without
|
||||||
others being informed.
|
others in the room being informed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = "whisper"
|
key = "whisper"
|
||||||
|
|
@ -440,24 +441,25 @@ class CmdWhisper(COMMAND_DEFAULT_CLASS):
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
|
|
||||||
if not self.lhs or not self.rhs:
|
if not self.lhs or not self.rhs:
|
||||||
caller.msg("Usage: whisper <account> = <message>")
|
caller.msg("Usage: whisper <character> = <message>")
|
||||||
return
|
return
|
||||||
|
|
||||||
receiver = caller.search(self.lhs)
|
receivers = [recv.strip() for recv in self.lhs.split(",")]
|
||||||
|
|
||||||
if not receiver:
|
receivers = [caller.search(receiver) for receiver in receivers]
|
||||||
return
|
receivers = [recv for recv in receivers if recv]
|
||||||
|
|
||||||
speech = self.rhs
|
speech = self.rhs
|
||||||
# Call a hook to change the speech before whispering
|
|
||||||
speech = caller.at_before_say(speech, whisper=True, receiver=receiver)
|
|
||||||
|
|
||||||
# If the speech is empty, abort the command
|
# If the speech is empty, abort the command
|
||||||
if not speech:
|
if not speech or not receivers:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Call the at_after_whisper hook for feedback
|
# Call a hook to change the speech before whispering
|
||||||
caller.at_say(speech, receiver=receiver, whisper=True)
|
speech = caller.at_before_say(speech, whisper=True, receivers=receivers)
|
||||||
|
|
||||||
|
# no need for self-message if we are whispering to ourselves (for some reason)
|
||||||
|
msg_self = None if caller in receivers else True
|
||||||
|
caller.at_say(speech, msg_self=msg_self, receivers=receivers, whisper=True)
|
||||||
|
|
||||||
|
|
||||||
class CmdPose(COMMAND_DEFAULT_CLASS):
|
class CmdPose(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
@mail/delete 6
|
@mail/delete 6
|
||||||
@mail/forward feend78 Griatch=4/You guys should read this.
|
@mail/forward feend78 Griatch=4/You guys should read this.
|
||||||
@mail/reply 9=Thanks for the info!
|
@mail/reply 9=Thanks for the info!
|
||||||
|
|
||||||
"""
|
"""
|
||||||
key = "@mail"
|
key = "@mail"
|
||||||
aliases = ["mail"]
|
aliases = ["mail"]
|
||||||
|
|
@ -86,6 +87,7 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
messages (list): list of Msg objects.
|
messages (list): list of Msg objects.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# mail_messages = Msg.objects.get_by_tag(category="mail")
|
# mail_messages = Msg.objects.get_by_tag(category="mail")
|
||||||
# messages = []
|
# messages = []
|
||||||
|
|
@ -105,6 +107,7 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
subject (str): The header or subject of the message to be delivered.
|
subject (str): The header or subject of the message to be delivered.
|
||||||
message (str): The body of the message being sent.
|
message (str): The body of the message being sent.
|
||||||
caller (obj): The object (or Account or Character) that is sending the message.
|
caller (obj): The object (or Account or Character) that is sending the message.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
for recipient in recipients:
|
for recipient in recipients:
|
||||||
recipient.msg("You have received a new @mail from %s" % caller)
|
recipient.msg("You have received a new @mail from %s" % caller)
|
||||||
|
|
@ -130,7 +133,8 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
all_mail = self.get_all_mail()
|
all_mail = self.get_all_mail()
|
||||||
mind = int(self.lhs) - 1
|
mind_max = all_mail.count() - 1
|
||||||
|
mind = max(0, min(mind_max, int(self.lhs) - 1))
|
||||||
if all_mail[mind]:
|
if all_mail[mind]:
|
||||||
all_mail[mind].delete()
|
all_mail[mind].delete()
|
||||||
self.caller.msg("Message %s deleted" % self.lhs)
|
self.caller.msg("Message %s deleted" % self.lhs)
|
||||||
|
|
@ -150,9 +154,10 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
all_mail = self.get_all_mail()
|
all_mail = self.get_all_mail()
|
||||||
|
mind_max = all_mail.count() - 1
|
||||||
if "/" in self.rhs:
|
if "/" in self.rhs:
|
||||||
message_number, message = self.rhs.split("/")
|
message_number, message = self.rhs.split("/", 1)
|
||||||
mind = int(message_number) - 1
|
mind = max(0, min(mind_max, int(message_number) - 1))
|
||||||
|
|
||||||
if all_mail[mind]:
|
if all_mail[mind]:
|
||||||
old_message = all_mail[mind]
|
old_message = all_mail[mind]
|
||||||
|
|
@ -164,7 +169,7 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
else:
|
else:
|
||||||
raise IndexError
|
raise IndexError
|
||||||
else:
|
else:
|
||||||
mind = int(self.rhs) - 1
|
mind = max(0, min(mind_max, int(self.rhs) - 1))
|
||||||
if all_mail[mind]:
|
if all_mail[mind]:
|
||||||
old_message = all_mail[mind]
|
old_message = all_mail[mind]
|
||||||
self.send_mail(self.search_targets(self.lhslist), "FWD: " + old_message.header,
|
self.send_mail(self.search_targets(self.lhslist), "FWD: " + old_message.header,
|
||||||
|
|
@ -188,7 +193,8 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
all_mail = self.get_all_mail()
|
all_mail = self.get_all_mail()
|
||||||
mind = int(self.lhs) - 1
|
mind_max = all_mail.count() - 1
|
||||||
|
mind = max(0, min(mind_max, int(self.lhs) - 1))
|
||||||
if all_mail[mind]:
|
if all_mail[mind]:
|
||||||
old_message = all_mail[mind]
|
old_message = all_mail[mind]
|
||||||
self.send_mail(old_message.senders, "RE: " + old_message.header,
|
self.send_mail(old_message.senders, "RE: " + old_message.header,
|
||||||
|
|
@ -211,8 +217,11 @@ class CmdMail(default_cmds.MuxCommand):
|
||||||
body = self.rhs
|
body = self.rhs
|
||||||
self.send_mail(self.search_targets(self.lhslist), subject, body, self.caller)
|
self.send_mail(self.search_targets(self.lhslist), subject, body, self.caller)
|
||||||
else:
|
else:
|
||||||
|
all_mail = self.get_all_mail()
|
||||||
|
mind_max = all_mail.count() - 1
|
||||||
try:
|
try:
|
||||||
message = self.get_all_mail()[int(self.lhs) - 1]
|
mind = max(0, min(mind_max, self.lhs - 1))
|
||||||
|
message = all_mail[mind]
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
self.caller.msg("'%s' is not a valid mail id." % self.lhs)
|
self.caller.msg("'%s' is not a valid mail id." % self.lhs)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ also adds the short descriptions and the `sdesc` command).
|
||||||
Installation:
|
Installation:
|
||||||
|
|
||||||
Edit `mygame/commands/default_cmdsets.py` and add
|
Edit `mygame/commands/default_cmdsets.py` and add
|
||||||
`from contrib.multidesc import CmdMultiDesc` to the top.
|
`from evennia.contrib.multidescer import CmdMultiDesc` to the top.
|
||||||
|
|
||||||
Next, look up the `at_cmdset_create` method of the `CharacterCmdSet`
|
Next, look up the `at_cmdset_create` method of the `CharacterCmdSet`
|
||||||
class and add a line `self.add(CmdMultiDesc())` to the end
|
class and add a line `self.add(CmdMultiDesc())` to the end
|
||||||
|
|
|
||||||
|
|
@ -858,7 +858,7 @@ class CmdSay(RPCommand): # replaces standard say
|
||||||
return
|
return
|
||||||
|
|
||||||
# calling the speech hook on the location
|
# calling the speech hook on the location
|
||||||
speech = caller.location.at_say(caller, self.args)
|
speech = caller.location.at_before_say(caller, self.args)
|
||||||
# preparing the speech with sdesc/speech parsing.
|
# preparing the speech with sdesc/speech parsing.
|
||||||
speech = "/me says, \"{speech}\"".format(speech=speech)
|
speech = "/me says, \"{speech}\"".format(speech=speech)
|
||||||
targets = self.caller.location.contents
|
targets = self.caller.location.contents
|
||||||
|
|
|
||||||
|
|
@ -822,10 +822,8 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
||||||
returns the new clone name on the form keyXX
|
returns the new clone name on the form keyXX
|
||||||
"""
|
"""
|
||||||
key = self.key
|
key = self.key
|
||||||
num = 1
|
num = sum(1 for obj in self.location.contents
|
||||||
for inum in (obj for obj in self.location.contents
|
if obj.key.startswith(key) and obj.key.lstrip(key).isdigit())
|
||||||
if obj.key.startswith(key) and obj.key.lstrip(key).isdigit()):
|
|
||||||
num += 1
|
|
||||||
return "%s%03i" % (key, num)
|
return "%s%03i" % (key, num)
|
||||||
new_key = new_key or find_clone_key()
|
new_key = new_key or find_clone_key()
|
||||||
return ObjectDB.objects.copy_object(self, new_key=new_key)
|
return ObjectDB.objects.copy_object(self, new_key=new_key)
|
||||||
|
|
@ -1205,7 +1203,7 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
||||||
|
|
||||||
mapping.update({
|
mapping.update({
|
||||||
"object": self,
|
"object": self,
|
||||||
"exit": exits[0] if exits else "somwhere",
|
"exit": exits[0] if exits else "somewhere",
|
||||||
"origin": location or "nowhere",
|
"origin": location or "nowhere",
|
||||||
"destination": destination or "nowhere",
|
"destination": destination or "nowhere",
|
||||||
})
|
})
|
||||||
|
|
@ -1562,7 +1560,7 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
||||||
a say. This is sent by the whisper command by default.
|
a say. This is sent by the whisper command by default.
|
||||||
Other verbal commands could use this hook in similar
|
Other verbal commands could use this hook in similar
|
||||||
ways.
|
ways.
|
||||||
receiver (Object): If set, this is a target for the say/whisper.
|
receivers (Object or iterable): If set, this is the target or targets for the say/whisper.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
message (str): The (possibly modified) text to be spoken.
|
message (str): The (possibly modified) text to be spoken.
|
||||||
|
|
@ -1571,7 +1569,7 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def at_say(self, message, msg_self=None, msg_location=None,
|
def at_say(self, message, msg_self=None, msg_location=None,
|
||||||
receiver=None, msg_receiver=None, mapping=None, **kwargs):
|
receivers=None, msg_receivers=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Display the actual say (or whisper) of self.
|
Display the actual say (or whisper) of self.
|
||||||
|
|
||||||
|
|
@ -1582,69 +1580,98 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
|
||||||
re-writing it completely.
|
re-writing it completely.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message (str): The text to be conveyed by self.
|
message (str): The message to convey.
|
||||||
msg_self (str, optional): The message to echo to self.
|
msg_self (bool or str, optional): If boolean True, echo `message` to self. If a string,
|
||||||
|
return that message. If False or unset, don't echo to self.
|
||||||
msg_location (str, optional): The message to echo to self's location.
|
msg_location (str, optional): The message to echo to self's location.
|
||||||
receiver (Object, optional): An eventual receiver of the message
|
receivers (Object or iterable, optional): An eventual receiver or receivers of the message
|
||||||
(by default only used by whispers).
|
(by default only used by whispers).
|
||||||
msg_receiver(str, optional): Specific message for receiver only.
|
msg_receivers(str): Specific message to pass to the receiver(s). This will parsed
|
||||||
mapping (dict, optional): Additional mapping in messages.
|
with the {receiver} placeholder replaced with the given receiver.
|
||||||
Kwargs:
|
Kwargs:
|
||||||
whisper (bool): If this is a whisper rather than a say. Kwargs
|
whisper (bool): If this is a whisper rather than a say. Kwargs
|
||||||
can be used by other verbal commands in a similar way.
|
can be used by other verbal commands in a similar way.
|
||||||
|
mapping (dict): Pass an additional mapping to the message.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
Messages can contain {} markers, which must
|
|
||||||
If used, `msg_self`, `msg_receiver` and `msg_location` should contain
|
Messages can contain {} markers. These are substituted against the values
|
||||||
references to other objects between braces, the way `location.msg_contents`
|
passed in the `mapping` argument.
|
||||||
would allow. For instance:
|
|
||||||
msg_self = 'You say: "{speech}"'
|
msg_self = 'You say: "{speech}"'
|
||||||
msg_location = '{object} says: "{speech}"'
|
msg_location = '{object} says: "{speech}"'
|
||||||
msg_receiver = '{object} whispers: "{speech}"'
|
msg_receivers = '{object} whispers: "{speech}"'
|
||||||
|
|
||||||
The following mappings can be used in both messages:
|
Supported markers by default:
|
||||||
object: the object speaking.
|
{self}: text to self-reference with (default 'You')
|
||||||
location: the location where object is.
|
{speech}: the text spoken/whispered by self.
|
||||||
speech: the text spoken by self.
|
{object}: the object speaking.
|
||||||
|
{receiver}: replaced with a single receiver only for strings meant for a specific
|
||||||
You can use additional mappings if you want to add other
|
receiver (otherwise 'None').
|
||||||
information in your messages.
|
{all_receivers}: comma-separated list of all receivers,
|
||||||
|
if more than one, otherwise same as receiver
|
||||||
|
{location}: the location where object is.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
msg_type = 'say'
|
||||||
if kwargs.get("whisper", False):
|
if kwargs.get("whisper", False):
|
||||||
# whisper mode
|
# whisper mode
|
||||||
msg_self = msg_self or 'You whisper to {receiver}, "{speech}"|n'
|
msg_type = 'whisper'
|
||||||
msg_receiver = msg_receiver or '{object} whispers: "{speech}"|n'
|
msg_self = '{self} whisper to {all_receivers}, "{speech}"' if msg_self is True else msg_self
|
||||||
|
msg_receivers = '{object} whispers: "{speech}"'
|
||||||
msg_location = None
|
msg_location = None
|
||||||
else:
|
else:
|
||||||
msg_self = msg_self or 'You say, "{speech}"|n'
|
msg_self = '{self} say, "{speech}"' if msg_self is True else msg_self
|
||||||
msg_receiver = None
|
msg_receivers = None
|
||||||
msg_location = msg_location or '{object} says, "{speech}"|n'
|
msg_location = msg_location or '{object} says, "{speech}"'
|
||||||
|
|
||||||
mapping = mapping or {}
|
custom_mapping = kwargs.get('mapping', {})
|
||||||
mapping.update({
|
receivers = make_iter(receivers) if receivers else None
|
||||||
"object": self,
|
location = self.location
|
||||||
"location": self.location,
|
|
||||||
"speech": message,
|
|
||||||
"receiver": receiver
|
|
||||||
})
|
|
||||||
|
|
||||||
if msg_self:
|
if msg_self:
|
||||||
self_mapping = {key: "yourself" if key == "receiver" and val is self
|
self_mapping = {"self": "You",
|
||||||
else val.get_display_name(self) if hasattr(val, "get_display_name")
|
"object": self.get_display_name(self),
|
||||||
else str(val) for key, val in mapping.items()}
|
"location": location.get_display_name(self) if location else None,
|
||||||
self.msg(msg_self.format(**self_mapping))
|
"receiver": None,
|
||||||
|
"all_receivers": ", ".join(
|
||||||
|
recv.get_display_name(self)
|
||||||
|
for recv in receivers) if receivers else None,
|
||||||
|
"speech": message}
|
||||||
|
self_mapping.update(custom_mapping)
|
||||||
|
self.msg(text=(msg_self.format(**self_mapping), {"type": msg_type}))
|
||||||
|
|
||||||
if receiver and msg_receiver:
|
if receivers and msg_receivers:
|
||||||
receiver_mapping = {key: val.get_display_name(receiver)
|
receiver_mapping = {"self": "You",
|
||||||
if hasattr(val, "get_display_name")
|
"object": None,
|
||||||
else str(val) for key, val in mapping.items()}
|
"location": None,
|
||||||
receiver.msg(msg_receiver.format(**receiver_mapping))
|
"receiver": None,
|
||||||
|
"all_receivers": None,
|
||||||
|
"speech": message}
|
||||||
|
for receiver in make_iter(receivers):
|
||||||
|
individual_mapping = {"object": self.get_display_name(receiver),
|
||||||
|
"location": location.get_display_name(receiver),
|
||||||
|
"receiver": receiver.get_display_name(receiver),
|
||||||
|
"all_receivers": ", ".join(
|
||||||
|
recv.get_display_name(recv)
|
||||||
|
for recv in receivers) if receivers else None}
|
||||||
|
receiver_mapping.update(individual_mapping)
|
||||||
|
receiver_mapping.update(custom_mapping)
|
||||||
|
receiver.msg(text=(msg_receivers.format(**receiver_mapping), {"type": msg_type}))
|
||||||
|
|
||||||
if self.location and msg_location:
|
if self.location and msg_location:
|
||||||
self.location.msg_contents(msg_location, exclude=(self, ),
|
location_mapping = {"self": "You",
|
||||||
mapping=mapping)
|
"object": self,
|
||||||
|
"location": location,
|
||||||
|
"all_receivers": ", ".join(recv for recv in receivers) if receivers else None,
|
||||||
|
"receiver": None,
|
||||||
|
"speech": message}
|
||||||
|
location_mapping.update(custom_mapping)
|
||||||
|
self.location.msg_contents(text=(msg_location, {"type": msg_type}),
|
||||||
|
from_obj=self,
|
||||||
|
exclude=(self, ) if msg_self else None,
|
||||||
|
mapping=location_mapping)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, connection
|
from django.db import migrations, connection
|
||||||
|
|
||||||
|
_ENGINE = None
|
||||||
|
|
||||||
def _table_exists(db_cursor, tablename):
|
def _table_exists(db_cursor, tablename):
|
||||||
"Returns bool if table exists or not"
|
"Returns bool if table exists or not"
|
||||||
|
|
@ -11,9 +12,25 @@ def _table_exists(db_cursor, tablename):
|
||||||
|
|
||||||
|
|
||||||
def _drop_table(db_cursor, table_name):
|
def _drop_table(db_cursor, table_name):
|
||||||
|
global _ENGINE
|
||||||
|
if not _ENGINE:
|
||||||
|
from django.conf import settings
|
||||||
|
try:
|
||||||
|
_ENGINE = settings.DATABASES["default"]["ENGINE"]
|
||||||
|
except KeyError:
|
||||||
|
_ENGINE = settings.DATABASE_ENGINE
|
||||||
|
|
||||||
if _table_exists(db_cursor, table_name):
|
if _table_exists(db_cursor, table_name):
|
||||||
sql_drop = "DROP TABLE %s;" % table_name
|
if _ENGINE == "django.db.backends.mysql":
|
||||||
db_cursor.execute(sql_drop)
|
db_cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
|
||||||
|
db_cursor.execute("DROP TABLE {table};".format(table=table_name))
|
||||||
|
db_cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
|
||||||
|
elif _ENGINE == "postgresql_psycopg2":
|
||||||
|
db_cursor.execute("ALTER TABLE {table} DISABLE TRIGGER ALL;".format(table=table_name))
|
||||||
|
db_cursor.execute("DROP TABLE {table};".format(table=table_name))
|
||||||
|
db_cursor.execute("ALTER TABLE {table} ENABLE TRIGGER ALL;".format(table=table_name))
|
||||||
|
else: # sqlite3, other databases
|
||||||
|
db_cursor.execute("DROP TABLE {table};".format(table=table_name))
|
||||||
|
|
||||||
|
|
||||||
def drop_tables(apps, schema_migrator):
|
def drop_tables(apps, schema_migrator):
|
||||||
|
|
@ -23,6 +40,9 @@ def drop_tables(apps, schema_migrator):
|
||||||
_drop_table(db_cursor, "players_playerdb_db_tags")
|
_drop_table(db_cursor, "players_playerdb_db_tags")
|
||||||
_drop_table(db_cursor, "players_playerdb_groups")
|
_drop_table(db_cursor, "players_playerdb_groups")
|
||||||
_drop_table(db_cursor, "players_playerdb_user_permissions")
|
_drop_table(db_cursor, "players_playerdb_user_permissions")
|
||||||
|
_drop_table(db_cursor, "comms_msg_db_sender_players")
|
||||||
|
_drop_table(db_cursor, "comms_msg_db_receivers_players")
|
||||||
|
_drop_table(db_cursor, "comms_msg_db_hide_from_players")
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
|
||||||
|
|
@ -674,8 +674,9 @@ class TypedObject(SharedMemoryModel):
|
||||||
Displays the name of the object in a viewer-aware manner.
|
Displays the name of the object in a viewer-aware manner.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
looker (TypedObject): The object or account that is looking
|
looker (TypedObject, optional): The object or account that is looking
|
||||||
at/getting inforamtion for this object.
|
at/getting inforamtion for this object. If not given, some
|
||||||
|
'safe' minimum level should be returned.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
name (str): A string containing the name of the object,
|
name (str): A string containing the name of the object,
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ from django.conf import settings
|
||||||
from evennia.utils import utils
|
from evennia.utils import utils
|
||||||
|
|
||||||
_ENCODINGS = settings.ENCODINGS
|
_ENCODINGS = settings.ENCODINGS
|
||||||
_RE_INSERT = re.compile(r"^\#INSERT (.*)", re.MULTILINE)
|
_RE_INSERT = re.compile(r"^\#INSERT (.*)$", re.MULTILINE)
|
||||||
_RE_CLEANBLOCK = re.compile(r"^\#.*?$|^\s*$", re.MULTILINE)
|
_RE_CLEANBLOCK = re.compile(r"^\#.*?$|^\s*$", re.MULTILINE)
|
||||||
_RE_CMD_SPLIT = re.compile(r"^\#.*?$", re.MULTILINE)
|
_RE_CMD_SPLIT = re.compile(r"^\#.*?$", re.MULTILINE)
|
||||||
_RE_CODE_OR_HEADER = re.compile(r"((?:\A|^)#CODE|(?:/A|^)#HEADER|\A)(.*?)$(.*?)(?=^#CODE.*?$|^#HEADER.*?$|\Z)",
|
_RE_CODE_OR_HEADER = re.compile(r"((?:\A|^)#CODE|(?:/A|^)#HEADER|\A)(.*?)$(.*?)(?=^#CODE.*?$|^#HEADER.*?$|\Z)",
|
||||||
|
|
@ -273,15 +273,10 @@ class BatchCommandProcessor(object):
|
||||||
|
|
||||||
def replace_insert(match):
|
def replace_insert(match):
|
||||||
"""Map replace entries"""
|
"""Map replace entries"""
|
||||||
return "\n#".join(self.parse_file(match.group(1)))
|
return "\n#\n".join(self.parse_file(match.group(1)))
|
||||||
|
|
||||||
# insert commands from inserted files
|
|
||||||
text = _RE_INSERT.sub(replace_insert, text)
|
text = _RE_INSERT.sub(replace_insert, text)
|
||||||
# re.sub(r"^\#INSERT (.*?)", replace_insert, text, flags=re.MULTILINE)
|
|
||||||
# get all commands
|
|
||||||
commands = _RE_CMD_SPLIT.split(text)
|
commands = _RE_CMD_SPLIT.split(text)
|
||||||
# re.split(r"^\#.*?$", text, flags=re.MULTILINE)
|
|
||||||
# remove eventual newline at the end of commands
|
|
||||||
commands = [c.strip('\r\n') for c in commands]
|
commands = [c.strip('\r\n') for c in commands]
|
||||||
commands = [c for c in commands if c]
|
commands = [c for c in commands if c]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -283,64 +283,64 @@ def parse_inlinefunc(string, strip=False, **kwargs):
|
||||||
# no cached stack; build a new stack and continue
|
# no cached stack; build a new stack and continue
|
||||||
stack = ParseStack()
|
stack = ParseStack()
|
||||||
|
|
||||||
# process string on stack
|
# process string on stack
|
||||||
ncallable = 0
|
ncallable = 0
|
||||||
for match in _RE_TOKEN.finditer(string):
|
for match in _RE_TOKEN.finditer(string):
|
||||||
gdict = match.groupdict()
|
gdict = match.groupdict()
|
||||||
if gdict["singlequote"]:
|
if gdict["singlequote"]:
|
||||||
stack.append(gdict["singlequote"])
|
stack.append(gdict["singlequote"])
|
||||||
elif gdict["doublequote"]:
|
elif gdict["doublequote"]:
|
||||||
stack.append(gdict["doublequote"])
|
stack.append(gdict["doublequote"])
|
||||||
elif gdict["end"]:
|
elif gdict["end"]:
|
||||||
if ncallable <= 0:
|
if ncallable <= 0:
|
||||||
stack.append(")")
|
stack.append(")")
|
||||||
continue
|
continue
|
||||||
args = []
|
args = []
|
||||||
while stack:
|
while stack:
|
||||||
operation = stack.pop()
|
operation = stack.pop()
|
||||||
if callable(operation):
|
if callable(operation):
|
||||||
if not strip:
|
if not strip:
|
||||||
stack.append((operation, [arg for arg in reversed(args)]))
|
stack.append((operation, [arg for arg in reversed(args)]))
|
||||||
ncallable -= 1
|
ncallable -= 1
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
args.append(operation)
|
||||||
|
elif gdict["start"]:
|
||||||
|
funcname = _RE_STARTTOKEN.match(gdict["start"]).group(1)
|
||||||
|
try:
|
||||||
|
# try to fetch the matching inlinefunc from storage
|
||||||
|
stack.append(_INLINE_FUNCS[funcname])
|
||||||
|
except KeyError:
|
||||||
|
stack.append(_INLINE_FUNCS["nomatch"])
|
||||||
|
stack.append(funcname)
|
||||||
|
ncallable += 1
|
||||||
|
elif gdict["escaped"]:
|
||||||
|
# escaped tokens
|
||||||
|
token = gdict["escaped"].lstrip("\\")
|
||||||
|
stack.append(token)
|
||||||
|
elif gdict["comma"]:
|
||||||
|
if ncallable > 0:
|
||||||
|
# commas outside strings and inside a callable are
|
||||||
|
# used to mark argument separation - we use None
|
||||||
|
# in the stack to indicate such a separation.
|
||||||
|
stack.append(None)
|
||||||
else:
|
else:
|
||||||
args.append(operation)
|
# no callable active - just a string
|
||||||
elif gdict["start"]:
|
stack.append(",")
|
||||||
funcname = _RE_STARTTOKEN.match(gdict["start"]).group(1)
|
|
||||||
try:
|
|
||||||
# try to fetch the matching inlinefunc from storage
|
|
||||||
stack.append(_INLINE_FUNCS[funcname])
|
|
||||||
except KeyError:
|
|
||||||
stack.append(_INLINE_FUNCS["nomatch"])
|
|
||||||
stack.append(funcname)
|
|
||||||
ncallable += 1
|
|
||||||
elif gdict["escaped"]:
|
|
||||||
# escaped tokens
|
|
||||||
token = gdict["escaped"].lstrip("\\")
|
|
||||||
stack.append(token)
|
|
||||||
elif gdict["comma"]:
|
|
||||||
if ncallable > 0:
|
|
||||||
# commas outside strings and inside a callable are
|
|
||||||
# used to mark argument separation - we use None
|
|
||||||
# in the stack to indicate such a separation.
|
|
||||||
stack.append(None)
|
|
||||||
else:
|
else:
|
||||||
# no callable active - just a string
|
# the rest
|
||||||
stack.append(",")
|
stack.append(gdict["rest"])
|
||||||
|
|
||||||
|
if ncallable > 0:
|
||||||
|
# this means not all inlinefuncs were complete
|
||||||
|
return string
|
||||||
|
|
||||||
|
if _STACK_MAXSIZE > 0 and _STACK_MAXSIZE < len(stack):
|
||||||
|
# if stack is larger than limit, throw away parsing
|
||||||
|
return string + gdict["stackfull"](*args, **kwargs)
|
||||||
else:
|
else:
|
||||||
# the rest
|
# cache the stack
|
||||||
stack.append(gdict["rest"])
|
_PARSING_CACHE[string] = stack
|
||||||
|
|
||||||
if ncallable > 0:
|
|
||||||
# this means not all inlinefuncs were complete
|
|
||||||
return string
|
|
||||||
|
|
||||||
if _STACK_MAXSIZE > 0 and _STACK_MAXSIZE < len(stack):
|
|
||||||
# if stack is larger than limit, throw away parsing
|
|
||||||
return string + gdict["stackfull"](*args, **kwargs)
|
|
||||||
else:
|
|
||||||
# cache the stack
|
|
||||||
_PARSING_CACHE[string] = stack
|
|
||||||
|
|
||||||
# run the stack recursively
|
# run the stack recursively
|
||||||
def _run_stack(item, depth=0):
|
def _run_stack(item, depth=0):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue