Move commands into a separate command module
authorJeremy Stanley <fungi@yuggoth.org>
Fri, 9 Nov 2018 21:54:21 +0000 (21:54 +0000)
committerJeremy Stanley <fungi@yuggoth.org>
Fri, 9 Nov 2018 22:00:35 +0000 (22:00 +0000)
For ease of maintainability, move all the mudpy.misc.command_*()
functions into their own module accessible via mudpy.command.*()
instead. In order to accomplish this, User objects now carry a
universe attribute so that commands they call can identify the
correct universe object in which to act.

Alphabetize the command functions, update the corresponding function
calls in the command elements, add the new module to the API
documentation, and include it in the dynamic module reload list.

doc/source/api.rst
mudpy/__init__.py
mudpy/command.py [new file with mode: 0644]
mudpy/misc.py
share/command.yaml

index 785e136..1b028ef 100644 (file)
@@ -9,6 +9,14 @@
 Submodules
 ----------
 
+mudpy\.command module
+---------------------
+
+.. automodule:: mudpy.command
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
 mudpy\.daemon module
 --------------------
 
index 38a69af..59128e8 100644 (file)
@@ -29,5 +29,5 @@ def load():
 
 
 # load the modules contained in this package
-modules = ["data", "misc", "password", "telnet", "version"]
+modules = ["command", "data", "misc", "password", "telnet", "version"]
 load()
diff --git a/mudpy/command.py b/mudpy/command.py
new file mode 100644 (file)
index 0000000..14640da
--- /dev/null
@@ -0,0 +1,494 @@
+"""User command functions for the mudpy engine."""
+
+# Copyright (c) 2004-2018 mudpy authors. Permission to use, copy,
+# modify, and distribute this software is granted under terms
+# provided in the LICENSE file distributed with this software.
+
+import random
+import re
+import unicodedata
+
+import mudpy
+
+
+def chat(actor):
+    """Toggle chat mode."""
+    mode = actor.get("mode")
+    if not mode:
+        actor.set("mode", "chat")
+        actor.send("Entering chat mode (use $(grn)!chat$(nrm) to exit).")
+    elif mode == "chat":
+        actor.remove_facet("mode")
+        actor.send("Exiting chat mode.")
+    else:
+        actor.send("Sorry, but you're already busy with something else!")
+
+
+def create(actor, parameters):
+    """Create an element if it does not exist."""
+    if not parameters:
+        message = "You must at least specify an element to create."
+    elif not actor.owner:
+        message = ""
+    else:
+        arguments = parameters.split()
+        if len(arguments) == 1:
+            arguments.append("")
+        if len(arguments) == 2:
+            element, filename = arguments
+            if element in actor.universe.contents:
+                message = 'The "' + element + '" element already exists.'
+            else:
+                message = ('You create "' +
+                           element + '" within the universe.')
+                logline = actor.owner.account.get(
+                    "name"
+                ) + " created an element: " + element
+                if filename:
+                    logline += " in file " + filename
+                    if filename not in actor.universe.files:
+                        message += (
+                            ' Warning: "' + filename + '" is not yet '
+                            "included in any other file and will not be read "
+                            "on startup unless this is remedied.")
+                mudpy.misc.Element(element, actor.universe, filename)
+                mudpy.misc.log(logline, 6)
+        elif len(arguments) > 2:
+            message = "You can only specify an element and a filename."
+    actor.send(message)
+
+
+def delete(actor, parameters):
+    """Delete a facet from an element."""
+    if not parameters:
+        message = "You must specify an element and a facet."
+    else:
+        arguments = parameters.split(" ")
+        if len(arguments) == 1:
+            message = ('What facet of element "' + arguments[0]
+                       + '" would you like to delete?')
+        elif len(arguments) != 2:
+            message = "You may only specify an element and a facet."
+        else:
+            element, facet = arguments
+            if element not in actor.universe.contents:
+                message = 'The "' + element + '" element does not exist.'
+            elif facet not in actor.universe.contents[element].facets():
+                message = ('The "' + element + '" element has no "' + facet
+                           + '" facet.')
+            else:
+                actor.universe.contents[element].remove_facet(facet)
+                message = ('You have successfully deleted the "' + facet
+                           + '" facet of element "' + element
+                           + '". Try "show element ' +
+                           element + '" for verification.')
+    actor.send(message)
+
+
+def destroy(actor, parameters):
+    """Destroy an element if it exists."""
+    if actor.owner:
+        if not parameters:
+            message = "You must specify an element to destroy."
+        else:
+            if parameters not in actor.universe.contents:
+                message = 'The "' + parameters + '" element does not exist.'
+            else:
+                actor.universe.contents[parameters].destroy()
+                message = ('You destroy "' + parameters
+                           + '" within the universe.')
+                mudpy.misc.log(
+                    actor.owner.account.get(
+                        "name"
+                    ) + " destroyed an element: " + parameters,
+                    6
+                )
+        actor.send(message)
+
+
+def error(actor, input_data):
+    """Generic error for an unrecognized command word."""
+
+    # 90% of the time use a generic error
+    if random.randrange(10):
+        message = '''I'm not sure what "''' + input_data + '''" means...'''
+
+    # 10% of the time use the classic diku error
+    else:
+        message = "Arglebargle, glop-glyf!?!"
+
+    # send the error message
+    actor.send(message)
+
+
+def halt(actor, parameters):
+    """Halt the world."""
+    if actor.owner:
+
+        # see if there's a message or use a generic one
+        if parameters:
+            message = "Halting: " + parameters
+        else:
+            message = "User " + actor.owner.account.get(
+                "name"
+            ) + " halted the world."
+
+        # let everyone know
+        mudpy.misc.broadcast(message, add_prompt=False)
+        mudpy.misc.log(message, 8)
+
+        # set a flag to terminate the world
+        actor.universe.terminate_flag = True
+
+
+def help(actor, parameters):
+    """List available commands and provide help for commands."""
+
+    # did the user ask for help on a specific command word?
+    if parameters and actor.owner:
+
+        # is the command word one for which we have data?
+        if parameters in actor.universe.groups["command"]:
+            command = actor.universe.groups["command"][parameters]
+        else:
+            command = None
+
+        # only for allowed commands
+        if actor.can_run(command):
+
+            # add a description if provided
+            description = command.get("description")
+            if not description:
+                description = "(no short description provided)"
+            if command.get("administrative"):
+                output = "$(red)"
+            else:
+                output = "$(grn)"
+            output += parameters + "$(nrm) - " + description + "$(eol)$(eol)"
+
+            # add the help text if provided
+            help_text = command.get("help")
+            if not help_text:
+                help_text = "No help is provided for this command."
+            output += help_text
+
+            # list related commands
+            see_also = command.get("see_also")
+            if see_also:
+                really_see_also = ""
+                for item in see_also:
+                    if item in actor.universe.groups["command"]:
+                        command = actor.universe.groups["command"][item]
+                        if actor.can_run(command):
+                            if really_see_also:
+                                really_see_also += ", "
+                            if command.get("administrative"):
+                                really_see_also += "$(red)"
+                            else:
+                                really_see_also += "$(grn)"
+                            really_see_also += item + "$(nrm)"
+                if really_see_also:
+                    output += "$(eol)$(eol)See also: " + really_see_also
+
+        # no data for the requested command word
+        else:
+            output = "That is not an available command."
+
+    # no specific command word was indicated
+    else:
+
+        # give a sorted list of commands with descriptions if provided
+        output = "These are the commands available to you:$(eol)$(eol)"
+        sorted_commands = list(actor.universe.groups["command"].keys())
+        sorted_commands.sort()
+        for item in sorted_commands:
+            command = actor.universe.groups["command"][item]
+            if actor.can_run(command):
+                description = command.get("description")
+                if not description:
+                    description = "(no short description provided)"
+                if command.get("administrative"):
+                    output += "   $(red)"
+                else:
+                    output += "   $(grn)"
+                output += item + "$(nrm) - " + description + "$(eol)"
+        output += ('$(eol)Enter "help COMMAND" for help on a command '
+                   'named "COMMAND".')
+
+    # send the accumulated output to the user
+    actor.send(output)
+
+
+def look(actor, parameters):
+    """Look around."""
+    if parameters:
+        actor.send("You can't look at or in anything yet.")
+    else:
+        actor.look_at(actor.get("location"))
+
+
+def move(actor, parameters):
+    """Move the avatar in a given direction."""
+    if parameters in actor.universe.contents[actor.get("location")].portals():
+        actor.move_direction(parameters)
+    else:
+        actor.send("You cannot go that way.")
+
+
+def quit(actor):
+    """Leave the world and go back to the main menu."""
+    if actor.owner:
+        actor.owner.state = "main_utility"
+        actor.owner.deactivate_avatar()
+
+
+def reload(actor):
+    """Reload all code modules, configs and data."""
+    if actor.owner:
+
+        # let the user know and log
+        actor.send("Reloading all code modules, configs and data.")
+        mudpy.misc.log(
+            "User " +
+            actor.owner.account.get("name") + " reloaded the world.",
+            6
+        )
+
+        # set a flag to reload
+        actor.universe.reload_flag = True
+
+
+def say(actor, parameters):
+    """Speak to others in the same area."""
+
+    # check for replacement macros and escape them
+    parameters = mudpy.misc.escape_macros(parameters)
+
+    # if the message is wrapped in quotes, remove them and leave contents
+    # intact
+    if parameters.startswith('"') and parameters.endswith('"'):
+        message = parameters[1:-1]
+        literal = True
+
+    # otherwise, get rid of stray quote marks on the ends of the message
+    else:
+        message = parameters.strip('''"'`''')
+        literal = False
+
+    # the user entered a message
+    if message:
+
+        # match the punctuation used, if any, to an action
+        if "mudpy.linguistic" in actor.universe.contents:
+            actions = actor.universe.contents[
+                "mudpy.linguistic"].get("actions", {})
+            default_punctuation = (actor.universe.contents[
+                "mudpy.linguistic"].get("default_punctuation", "."))
+        else:
+            actions = {}
+            default_punctuation = "."
+        action = ""
+
+        # reverse sort punctuation options so the longest match wins
+        for mark in sorted(actions.keys(), reverse=True):
+            if not literal and message.endswith(mark):
+                action = actions[mark]
+                break
+
+        # add punctuation if needed
+        if not action:
+            action = actions[default_punctuation]
+            if message and not (
+               literal or unicodedata.category(message[-1]) == "Po"
+               ):
+                message += default_punctuation
+
+        # failsafe checks to avoid unwanted reformatting and null strings
+        if message and not literal:
+
+            # decapitalize the first letter to improve matching
+            message = message[0].lower() + message[1:]
+
+            # iterate over all words in message, replacing typos
+            if "mudpy.linguistic" in actor.universe.contents:
+                typos = actor.universe.contents[
+                    "mudpy.linguistic"].get("typos", {})
+            else:
+                typos = {}
+            words = message.split()
+            for index in range(len(words)):
+                word = words[index]
+                while unicodedata.category(word[0]) == "Po":
+                    word = word[1:]
+                while unicodedata.category(word[-1]) == "Po":
+                    word = word[:-1]
+                if word in typos.keys():
+                    words[index] = words[index].replace(word, typos[word])
+            message = " ".join(words)
+
+            # capitalize the first letter
+            message = message[0].upper() + message[1:]
+
+    # tell the area
+    if message:
+        actor.echo_to_location(
+            actor.get("name") + " " + action + 's, "' + message + '"'
+        )
+        actor.send("You " + action + ', "' + message + '"')
+
+    # there was no message
+    else:
+        actor.send("What do you want to say?")
+
+
+def set(actor, parameters):
+    """Set a facet of an element."""
+    if not parameters:
+        message = "You must specify an element, a facet and a value."
+    else:
+        arguments = parameters.split(" ", 2)
+        if len(arguments) == 1:
+            message = ('What facet of element "' + arguments[0]
+                       + '" would you like to set?')
+        elif len(arguments) == 2:
+            message = ('What value would you like to set for the "' +
+                       arguments[1] + '" facet of the "' + arguments[0]
+                       + '" element?')
+        else:
+            element, facet, value = arguments
+            if element not in actor.universe.contents:
+                message = 'The "' + element + '" element does not exist.'
+            else:
+                try:
+                    actor.universe.contents[element].set(facet, value)
+                except PermissionError:
+                    message = ('The "%s" element is kept in read-only file '
+                               '"%s" and cannot be altered.' %
+                               (element, actor.universe.contents[
+                                        element].origin.source))
+                except ValueError:
+                    message = ('Value "%s" of type "%s" cannot be coerced '
+                               'to the correct datatype for facet "%s".' %
+                               (value, type(value), facet))
+                else:
+                    message = ('You have successfully (re)set the "' + facet
+                               + '" facet of element "' + element
+                               + '". Try "show element ' +
+                               element + '" for verification.')
+    actor.send(message)
+
+
+def show(actor, parameters):
+    """Show program data."""
+    message = ""
+    arguments = parameters.split()
+    if not parameters:
+        message = "What do you want to show?"
+    elif arguments[0] == "version":
+        message = repr(actor.universe.versions)
+    elif arguments[0] == "time":
+        message = actor.universe.groups["internal"]["counters"].get(
+            "elapsed"
+        ) + " increments elapsed since the world was created."
+    elif arguments[0] == "groups":
+        message = "These are the element groups:$(eol)"
+        groups = list(actor.universe.groups.keys())
+        groups.sort()
+        for group in groups:
+            message += "$(eol)   $(grn)" + group + "$(nrm)"
+    elif arguments[0] == "files":
+        message = "These are the current files containing the universe:$(eol)"
+        filenames = sorted(actor.universe.files)
+        for filename in filenames:
+            if actor.universe.files[filename].is_writeable():
+                status = "rw"
+            else:
+                status = "ro"
+            message += ("$(eol)   $(red)(%s) $(grn)%s$(nrm)" %
+                        (status, filename))
+            if actor.universe.files[filename].flags:
+                message += (" $(yel)[%s]$(nrm)" %
+                            ",".join(actor.universe.files[filename].flags))
+    elif arguments[0] == "group":
+        if len(arguments) != 2:
+            message = "You must specify one group."
+        elif arguments[1] in actor.universe.groups:
+            message = ('These are the elements in the "' + arguments[1]
+                       + '" group:$(eol)')
+            elements = [
+                (
+                    actor.universe.groups[arguments[1]][x].key
+                ) for x in actor.universe.groups[arguments[1]].keys()
+            ]
+            elements.sort()
+            for element in elements:
+                message += "$(eol)   $(grn)" + element + "$(nrm)"
+        else:
+            message = 'Group "' + arguments[1] + '" does not exist.'
+    elif arguments[0] == "file":
+        if len(arguments) != 2:
+            message = "You must specify one file."
+        elif arguments[1] in actor.universe.files:
+            message = ('These are the nodes in the "' + arguments[1]
+                       + '" file:$(eol)')
+            elements = sorted(actor.universe.files[arguments[1]].data)
+            for element in elements:
+                message += "$(eol)   $(grn)" + element + "$(nrm)"
+        else:
+            message = 'File "%s" does not exist.' % arguments[1]
+    elif arguments[0] == "element":
+        if len(arguments) != 2:
+            message = "You must specify one element."
+        elif arguments[1].strip(".") in actor.universe.contents:
+            element = actor.universe.contents[arguments[1].strip(".")]
+            message = ('These are the properties of the "' + arguments[1]
+                       + '" element (in "' + element.origin.source
+                       + '"):$(eol)')
+            facets = element.facets()
+            for facet in sorted(facets):
+                message += ("$(eol)   $(grn)%s: $(red)%s$(nrm)" %
+                            (facet, str(facets[facet])))
+        else:
+            message = 'Element "' + arguments[1] + '" does not exist.'
+    elif arguments[0] == "result":
+        if len(arguments) < 2:
+            message = "You need to specify an expression."
+        else:
+            try:
+                message = repr(eval(" ".join(arguments[1:])))
+            except Exception as e:
+                message = ("$(red)Your expression raised an exception...$(eol)"
+                           "$(eol)$(bld)%s$(nrm)" % e)
+    elif arguments[0] == "log":
+        if len(arguments) == 4:
+            if re.match(r"^\d+$", arguments[3]) and int(arguments[3]) >= 0:
+                stop = int(arguments[3])
+            else:
+                stop = -1
+        else:
+            stop = 0
+        if len(arguments) >= 3:
+            if re.match(r"^\d+$", arguments[2]) and int(arguments[2]) > 0:
+                start = int(arguments[2])
+            else:
+                start = -1
+        else:
+            start = 10
+        if len(arguments) >= 2:
+            if (re.match(r"^\d+$", arguments[1])
+                    and 0 <= int(arguments[1]) <= 9):
+                level = int(arguments[1])
+            else:
+                level = -1
+        elif 0 <= actor.owner.account.get("loglevel", 0) <= 9:
+            level = actor.owner.account.get("loglevel", 0)
+        else:
+            level = 1
+        if level > -1 and start > -1 and stop > -1:
+            message = mudpy.misc.get_loglines(level, start, stop)
+        else:
+            message = ("When specified, level must be 0-9 (default 1), "
+                       "start and stop must be >=1 (default 10 and 1).")
+    else:
+        message = '''I don't know what "''' + parameters + '" is.'
+    actor.send(message)
index f4168ee..930d4d7 100644 (file)
@@ -503,6 +503,7 @@ class User:
         self.password_tries = 0
         self.state = "telopt_negotiation"
         self.telopts = {}
+        self.universe = universe
 
     def quit(self):
         """Log, close the connection and remove."""
@@ -1853,494 +1854,13 @@ def handler_active(user):
 
         # otherwise, give an error
         elif command_name:
-            command_error(actor, input_data)
+            mudpy.command.error(actor, input_data)
 
     # if no input, just idle back with a prompt
     else:
         user.send("", just_prompt=True)
 
 
-def command_halt(actor, parameters):
-    """Halt the world."""
-    if actor.owner:
-
-        # see if there's a message or use a generic one
-        if parameters:
-            message = "Halting: " + parameters
-        else:
-            message = "User " + actor.owner.account.get(
-                "name"
-            ) + " halted the world."
-
-        # let everyone know
-        broadcast(message, add_prompt=False)
-        log(message, 8)
-
-        # set a flag to terminate the world
-        universe.terminate_flag = True
-
-
-def command_reload(actor):
-    """Reload all code modules, configs and data."""
-    if actor.owner:
-
-        # let the user know and log
-        actor.send("Reloading all code modules, configs and data.")
-        log(
-            "User " +
-            actor.owner.account.get("name") + " reloaded the world.",
-            6
-        )
-
-        # set a flag to reload
-        universe.reload_flag = True
-
-
-def command_quit(actor):
-    """Leave the world and go back to the main menu."""
-    if actor.owner:
-        actor.owner.state = "main_utility"
-        actor.owner.deactivate_avatar()
-
-
-def command_help(actor, parameters):
-    """List available commands and provide help for commands."""
-
-    # did the user ask for help on a specific command word?
-    if parameters and actor.owner:
-
-        # is the command word one for which we have data?
-        if parameters in universe.groups["command"]:
-            command = universe.groups["command"][parameters]
-        else:
-            command = None
-
-        # only for allowed commands
-        if actor.can_run(command):
-
-            # add a description if provided
-            description = command.get("description")
-            if not description:
-                description = "(no short description provided)"
-            if command.get("administrative"):
-                output = "$(red)"
-            else:
-                output = "$(grn)"
-            output += parameters + "$(nrm) - " + description + "$(eol)$(eol)"
-
-            # add the help text if provided
-            help_text = command.get("help")
-            if not help_text:
-                help_text = "No help is provided for this command."
-            output += help_text
-
-            # list related commands
-            see_also = command.get("see_also")
-            if see_also:
-                really_see_also = ""
-                for item in see_also:
-                    if item in universe.groups["command"]:
-                        command = universe.groups["command"][item]
-                        if actor.can_run(command):
-                            if really_see_also:
-                                really_see_also += ", "
-                            if command.get("administrative"):
-                                really_see_also += "$(red)"
-                            else:
-                                really_see_also += "$(grn)"
-                            really_see_also += item + "$(nrm)"
-                if really_see_also:
-                    output += "$(eol)$(eol)See also: " + really_see_also
-
-        # no data for the requested command word
-        else:
-            output = "That is not an available command."
-
-    # no specific command word was indicated
-    else:
-
-        # give a sorted list of commands with descriptions if provided
-        output = "These are the commands available to you:$(eol)$(eol)"
-        sorted_commands = list(universe.groups["command"].keys())
-        sorted_commands.sort()
-        for item in sorted_commands:
-            command = universe.groups["command"][item]
-            if actor.can_run(command):
-                description = command.get("description")
-                if not description:
-                    description = "(no short description provided)"
-                if command.get("administrative"):
-                    output += "   $(red)"
-                else:
-                    output += "   $(grn)"
-                output += item + "$(nrm) - " + description + "$(eol)"
-        output += ('$(eol)Enter "help COMMAND" for help on a command '
-                   'named "COMMAND".')
-
-    # send the accumulated output to the user
-    actor.send(output)
-
-
-def command_move(actor, parameters):
-    """Move the avatar in a given direction."""
-    if parameters in universe.contents[actor.get("location")].portals():
-        actor.move_direction(parameters)
-    else:
-        actor.send("You cannot go that way.")
-
-
-def command_look(actor, parameters):
-    """Look around."""
-    if parameters:
-        actor.send("You can't look at or in anything yet.")
-    else:
-        actor.look_at(actor.get("location"))
-
-
-def command_say(actor, parameters):
-    """Speak to others in the same area."""
-
-    # check for replacement macros and escape them
-    parameters = escape_macros(parameters)
-
-    # if the message is wrapped in quotes, remove them and leave contents
-    # intact
-    if parameters.startswith('"') and parameters.endswith('"'):
-        message = parameters[1:-1]
-        literal = True
-
-    # otherwise, get rid of stray quote marks on the ends of the message
-    else:
-        message = parameters.strip('''"'`''')
-        literal = False
-
-    # the user entered a message
-    if message:
-
-        # match the punctuation used, if any, to an action
-        if "mudpy.linguistic" in universe.contents:
-            actions = universe.contents["mudpy.linguistic"].get("actions", {})
-            default_punctuation = (universe.contents["mudpy.linguistic"].get(
-                "default_punctuation", "."))
-        else:
-            actions = {}
-            default_punctuation = "."
-        action = ""
-
-        # reverse sort punctuation options so the longest match wins
-        for mark in sorted(actions.keys(), reverse=True):
-            if not literal and message.endswith(mark):
-                action = actions[mark]
-                break
-
-        # add punctuation if needed
-        if not action:
-            action = actions[default_punctuation]
-            if message and not (
-               literal or unicodedata.category(message[-1]) == "Po"
-               ):
-                message += default_punctuation
-
-        # failsafe checks to avoid unwanted reformatting and null strings
-        if message and not literal:
-
-            # decapitalize the first letter to improve matching
-            message = message[0].lower() + message[1:]
-
-            # iterate over all words in message, replacing typos
-            if "mudpy.linguistic" in universe.contents:
-                typos = universe.contents["mudpy.linguistic"].get("typos", {})
-            else:
-                typos = {}
-            words = message.split()
-            for index in range(len(words)):
-                word = words[index]
-                while unicodedata.category(word[0]) == "Po":
-                    word = word[1:]
-                while unicodedata.category(word[-1]) == "Po":
-                    word = word[:-1]
-                if word in typos.keys():
-                    words[index] = words[index].replace(word, typos[word])
-            message = " ".join(words)
-
-            # capitalize the first letter
-            message = message[0].upper() + message[1:]
-
-    # tell the area
-    if message:
-        actor.echo_to_location(
-            actor.get("name") + " " + action + 's, "' + message + '"'
-        )
-        actor.send("You " + action + ', "' + message + '"')
-
-    # there was no message
-    else:
-        actor.send("What do you want to say?")
-
-
-def command_chat(actor):
-    """Toggle chat mode."""
-    mode = actor.get("mode")
-    if not mode:
-        actor.set("mode", "chat")
-        actor.send("Entering chat mode (use $(grn)!chat$(nrm) to exit).")
-    elif mode == "chat":
-        actor.remove_facet("mode")
-        actor.send("Exiting chat mode.")
-    else:
-        actor.send("Sorry, but you're already busy with something else!")
-
-
-def command_show(actor, parameters):
-    """Show program data."""
-    message = ""
-    arguments = parameters.split()
-    if not parameters:
-        message = "What do you want to show?"
-    elif arguments[0] == "version":
-        message = repr(universe.versions)
-    elif arguments[0] == "time":
-        message = universe.groups["internal"]["counters"].get(
-            "elapsed"
-        ) + " increments elapsed since the world was created."
-    elif arguments[0] == "groups":
-        message = "These are the element groups:$(eol)"
-        groups = list(universe.groups.keys())
-        groups.sort()
-        for group in groups:
-            message += "$(eol)   $(grn)" + group + "$(nrm)"
-    elif arguments[0] == "files":
-        message = "These are the current files containing the universe:$(eol)"
-        filenames = sorted(universe.files)
-        for filename in filenames:
-            if universe.files[filename].is_writeable():
-                status = "rw"
-            else:
-                status = "ro"
-            message += ("$(eol)   $(red)(%s) $(grn)%s$(nrm)" %
-                        (status, filename))
-            if universe.files[filename].flags:
-                message += (" $(yel)[%s]$(nrm)" %
-                            ",".join(universe.files[filename].flags))
-    elif arguments[0] == "group":
-        if len(arguments) != 2:
-            message = "You must specify one group."
-        elif arguments[1] in universe.groups:
-            message = ('These are the elements in the "' + arguments[1]
-                       + '" group:$(eol)')
-            elements = [
-                (
-                    universe.groups[arguments[1]][x].key
-                ) for x in universe.groups[arguments[1]].keys()
-            ]
-            elements.sort()
-            for element in elements:
-                message += "$(eol)   $(grn)" + element + "$(nrm)"
-        else:
-            message = 'Group "' + arguments[1] + '" does not exist.'
-    elif arguments[0] == "file":
-        if len(arguments) != 2:
-            message = "You must specify one file."
-        elif arguments[1] in universe.files:
-            message = ('These are the nodes in the "' + arguments[1]
-                       + '" file:$(eol)')
-            elements = sorted(universe.files[arguments[1]].data)
-            for element in elements:
-                message += "$(eol)   $(grn)" + element + "$(nrm)"
-        else:
-            message = 'File "%s" does not exist.' % arguments[1]
-    elif arguments[0] == "element":
-        if len(arguments) != 2:
-            message = "You must specify one element."
-        elif arguments[1].strip(".") in universe.contents:
-            element = universe.contents[arguments[1].strip(".")]
-            message = ('These are the properties of the "' + arguments[1]
-                       + '" element (in "' + element.origin.source
-                       + '"):$(eol)')
-            facets = element.facets()
-            for facet in sorted(facets):
-                message += ("$(eol)   $(grn)%s: $(red)%s$(nrm)" %
-                            (facet, str(facets[facet])))
-        else:
-            message = 'Element "' + arguments[1] + '" does not exist.'
-    elif arguments[0] == "result":
-        if len(arguments) < 2:
-            message = "You need to specify an expression."
-        else:
-            try:
-                message = repr(eval(" ".join(arguments[1:])))
-            except Exception as e:
-                message = ("$(red)Your expression raised an exception...$(eol)"
-                           "$(eol)$(bld)%s$(nrm)" % e)
-    elif arguments[0] == "log":
-        if len(arguments) == 4:
-            if re.match(r"^\d+$", arguments[3]) and int(arguments[3]) >= 0:
-                stop = int(arguments[3])
-            else:
-                stop = -1
-        else:
-            stop = 0
-        if len(arguments) >= 3:
-            if re.match(r"^\d+$", arguments[2]) and int(arguments[2]) > 0:
-                start = int(arguments[2])
-            else:
-                start = -1
-        else:
-            start = 10
-        if len(arguments) >= 2:
-            if (re.match(r"^\d+$", arguments[1])
-                    and 0 <= int(arguments[1]) <= 9):
-                level = int(arguments[1])
-            else:
-                level = -1
-        elif 0 <= actor.owner.account.get("loglevel", 0) <= 9:
-            level = actor.owner.account.get("loglevel", 0)
-        else:
-            level = 1
-        if level > -1 and start > -1 and stop > -1:
-            message = get_loglines(level, start, stop)
-        else:
-            message = ("When specified, level must be 0-9 (default 1), "
-                       "start and stop must be >=1 (default 10 and 1).")
-    else:
-        message = '''I don't know what "''' + parameters + '" is.'
-    actor.send(message)
-
-
-def command_create(actor, parameters):
-    """Create an element if it does not exist."""
-    if not parameters:
-        message = "You must at least specify an element to create."
-    elif not actor.owner:
-        message = ""
-    else:
-        arguments = parameters.split()
-        if len(arguments) == 1:
-            arguments.append("")
-        if len(arguments) == 2:
-            element, filename = arguments
-            if element in universe.contents:
-                message = 'The "' + element + '" element already exists.'
-            else:
-                message = ('You create "' +
-                           element + '" within the universe.')
-                logline = actor.owner.account.get(
-                    "name"
-                ) + " created an element: " + element
-                if filename:
-                    logline += " in file " + filename
-                    if filename not in universe.files:
-                        message += (
-                            ' Warning: "' + filename + '" is not yet '
-                            "included in any other file and will not be read "
-                            "on startup unless this is remedied.")
-                Element(element, universe, filename)
-                log(logline, 6)
-        elif len(arguments) > 2:
-            message = "You can only specify an element and a filename."
-    actor.send(message)
-
-
-def command_destroy(actor, parameters):
-    """Destroy an element if it exists."""
-    if actor.owner:
-        if not parameters:
-            message = "You must specify an element to destroy."
-        else:
-            if parameters not in universe.contents:
-                message = 'The "' + parameters + '" element does not exist.'
-            else:
-                universe.contents[parameters].destroy()
-                message = ('You destroy "' + parameters
-                           + '" within the universe.')
-                log(
-                    actor.owner.account.get(
-                        "name"
-                    ) + " destroyed an element: " + parameters,
-                    6
-                )
-        actor.send(message)
-
-
-def command_set(actor, parameters):
-    """Set a facet of an element."""
-    if not parameters:
-        message = "You must specify an element, a facet and a value."
-    else:
-        arguments = parameters.split(" ", 2)
-        if len(arguments) == 1:
-            message = ('What facet of element "' + arguments[0]
-                       + '" would you like to set?')
-        elif len(arguments) == 2:
-            message = ('What value would you like to set for the "' +
-                       arguments[1] + '" facet of the "' + arguments[0]
-                       + '" element?')
-        else:
-            element, facet, value = arguments
-            if element not in universe.contents:
-                message = 'The "' + element + '" element does not exist.'
-            else:
-                try:
-                    universe.contents[element].set(facet, value)
-                except PermissionError:
-                    message = ('The "%s" element is kept in read-only file '
-                               '"%s" and cannot be altered.' %
-                               (element, universe.contents[
-                                        element].origin.source))
-                except ValueError:
-                    message = ('Value "%s" of type "%s" cannot be coerced '
-                               'to the correct datatype for facet "%s".' %
-                               (value, type(value), facet))
-                else:
-                    message = ('You have successfully (re)set the "' + facet
-                               + '" facet of element "' + element
-                               + '". Try "show element ' +
-                               element + '" for verification.')
-    actor.send(message)
-
-
-def command_delete(actor, parameters):
-    """Delete a facet from an element."""
-    if not parameters:
-        message = "You must specify an element and a facet."
-    else:
-        arguments = parameters.split(" ")
-        if len(arguments) == 1:
-            message = ('What facet of element "' + arguments[0]
-                       + '" would you like to delete?')
-        elif len(arguments) != 2:
-            message = "You may only specify an element and a facet."
-        else:
-            element, facet = arguments
-            if element not in universe.contents:
-                message = 'The "' + element + '" element does not exist.'
-            elif facet not in universe.contents[element].facets():
-                message = ('The "' + element + '" element has no "' + facet
-                           + '" facet.')
-            else:
-                universe.contents[element].remove_facet(facet)
-                message = ('You have successfully deleted the "' + facet
-                           + '" facet of element "' + element
-                           + '". Try "show element ' +
-                           element + '" for verification.')
-    actor.send(message)
-
-
-def command_error(actor, input_data):
-    """Generic error for an unrecognized command word."""
-
-    # 90% of the time use a generic error
-    if random.randrange(10):
-        message = '''I'm not sure what "''' + input_data + '''" means...'''
-
-    # 10% of the time use the classic diku error
-    else:
-        message = "Arglebargle, glop-glyf!?!"
-
-    # send the error message
-    actor.send(message)
-
-
 def daemonize(universe):
     """Fork and disassociate from everything."""
 
index 83e3d09..6c399b2 100644 (file)
@@ -7,7 +7,7 @@ _desc: This is the standard library of command definitions.
 
 _lock: true
 
-command.chat.action: command_chat(actor)
+command.chat.action: mudpy.command.chat(actor)
 command.chat.description: Enter and leave chat mode.
 command.chat.help: The chat command toggles chat mode. When in chat mode, all
     input is passed as a parameter to the say command, unless prepended by an
@@ -15,57 +15,57 @@ command.chat.help: The chat command toggles chat mode. When in chat mode, all
     use:$(eol)$(eol)   !chat
 command.chat.see_also: say
 
-command.create.action: command_create(actor, parameters)
+command.create.action: mudpy.command.create(actor, parameters)
 command.create.administrative: true
 command.create.description: Create a new element in the universe.
 command.create.help: Ways to create an element:$(eol)$(eol)   create
     actor.avatar_fred_1$(eol)   create other.garply foo/bar/baz
 
-command.delete.action: command_delete(actor, parameters)
+command.delete.action: mudpy.command.delete(actor, parameters)
 command.delete.administrative: true
 command.delete.description: Delete an existing facet from an element.
 command.delete.help: You can delete any facet of an element as
     follows:$(eol)$(eol)   delete area.boardroom terrain
 
-command.destroy.action: command_destroy(actor, parameters)
+command.destroy.action: mudpy.command.destroy(actor, parameters)
 command.destroy.administrative: true
 command.destroy.description: Destroy an existing element in the universe.
 command.destroy.help: You can destroy any element in the universe as
     follows:$(eol)$(eol)   destroy prop.dagger
 
-command.halt.action: command_halt(actor, parameters)
+command.halt.action: mudpy.command.halt(actor, parameters)
 command.halt.administrative: true
 command.halt.description: Shut down the world.
 command.halt.help: This will save all active accounts, disconnect all clients
     and stop the entire program.
 
-command.help.action: command_help(actor, parameters)
+command.help.action: mudpy.command.help(actor, parameters)
 command.help.description: List commands or get help on one.
 command.help.help: This will list all comand words available to you along with
     a brief description or, alternatively, give you detailed information on one
     command.
 
-command.look.action: command_look(actor, parameters)
+command.look.action: mudpy.command.look(actor, parameters)
 command.look.description: Look around.
 command.look.help: With the look command, you can see where you are.
 
-command.move.action: command_move(actor, parameters)
+command.move.action: mudpy.command.move(actor, parameters)
 command.move.description: Move in a specific direction.
 command.move.help: You move in a direction by entering:$(eol)$(eol)   move
     north
 
-command.quit.action: command_quit(actor)
+command.quit.action: mudpy.command.quit(actor)
 command.quit.description: Leave the World.
 command.quit.help: This will deactivate your avatar and return you to the main
     menu.
 
-command.reload.action: command_reload(actor)
+command.reload.action: mudpy.command.reload(actor)
 command.reload.administrative: true
 command.reload.description: Reload modules and data.
 command.reload.help: This will reload all python modules and read-only data
     files.
 
-command.say.action: command_say(actor, parameters)
+command.say.action: mudpy.command.say(actor, parameters)
 command.say.description: State something out loud.
 command.say.help: This allows you to speak to other characters within the same
     area. If you end your sentence with punctuation, the message displayed will
@@ -78,14 +78,14 @@ command.say.help: This allows you to speak to other characters within the same
     went teh wrong way?"$(eol)   You say, "youre sure i went teh wrong way?"
 command.say.see_also: chat
 
-command.set.action: command_set(actor, parameters)
+command.set.action: mudpy.command.set(actor, parameters)
 command.set.administrative: true
 command.set.description: Set a facet of an element.
 command.set.help: Invoke it like
     this:$(eol)$(eol)   set actor.avatar_dominique_0 description You see
     nothing special.
 
-command.show.action: command_show(actor, parameters)
+command.show.action: mudpy.command.show(actor, parameters)
 command.show.administrative: true
 command.show.description: Show various data.
 command.show.help: Here are the possible incantations (<parameter> is required,