After lots of discussions, default commands where moved from game/gamesrc/commands/default to src/commands/default in order to make it clearer which parts are updated as part of evennia and which can be tweaked at heart's content. New templates where left in gamesrc/commands that should hopefully make it clearer how to extend the command system. Also game/web was moved to src/web - we'll likely extend this from game/gamesrc/web in the future. If you already did extensions you should just have to edit your import paths and make use of the new cmdset template supplied.

The unit testing was for commands was split out from src/objects/tests.py into the new src/commands/default/test.py in order to keep the testing modules thematically grouped with the things they are testing.
This commit is contained in:
Griatch 2010-11-23 01:24:56 +00:00
parent a3917073ff
commit 72d40285b8
61 changed files with 381 additions and 184 deletions

View file

@ -0,0 +1,297 @@
"""
The help command. The basic idea is that help texts for commands
are best written by those that write the commands - the admins. So
command-help is all auto-loaded and searched from the current command
set. The normal, database-tied help system is used for collaborative
creation of other help topics such as RP help or game-world aides.
"""
from src.utils.utils import fill, dedent
from src.commands.command import Command
from src.help.models import HelpEntry
from src.permissions.permissions import has_perm
from src.utils import create
from src.commands.default.muxcommand import MuxCommand
LIST_ARGS = ["list", "all"]
def format_help_entry(title, help_text, aliases=None,
suggested=None):
"""
This visually formats the help entry.
"""
string = "-"*70 + "\n"
if title:
string += "Help topic for {w%s{n" % (title.capitalize())
if aliases:
string += " (aliases: %s)" % (", ".join(aliases))
if help_text:
string += "\n%s" % dedent(help_text.rstrip())
if suggested:
string += "\nSuggested:\n"
string += fill(", ".join(suggested))
string.strip()
string += "\n" + "-"*70
return string
def format_help_list(hdict_cmds, hdict_db):
"""
Output a category-ordered list.
"""
string = ""
if hdict_cmds and hdict_cmds.values():
string += "\n\r" + "-"*70 + "\n\r {gCommand help entries{n\n" + "-"*70
for category in sorted(hdict_cmds.keys()):
string += "\n {w%s{n:\n" % \
(str(category).capitalize())
string += fill(", ".join(sorted(hdict_cmds[category])))
if hdict_db and hdict_db.values():
string += "\n\r\n\r" + "-"*70 + "\n\r {gOther help entries{n\n" + '-'*70
for category in sorted(hdict_db.keys()):
string += "\n\r {w%s{n:\n" % (str(category).capitalize())
string += fill(", ".join(sorted([str(topic) for topic in hdict_db[category]])))
return string
class CmdHelp(Command):
"""
The main help command
Usage:
help <topic or command>
help list
help all
This will search for help on commands and other
topics related to the game.
"""
key = "help"
# this is a special cmdhandler flag that makes the cmdhandler also pack
# the current cmdset with the call to self.func().
return_cmdset = True
def parse(self):
"""
inp is a string containing the command or topic match.
"""
self.args = self.args.strip().lower()
def func(self):
"""
Run the dynamic help entry creator.
"""
query, cmdset = self.args, self.cmdset
caller = self.caller
if not query:
query = "all"
# removing doublets in cmdset, caused by cmdhandler
# having to allow doublet commands to manage exits etc.
cmdset.make_unique(caller)
# Listing help entries
if query in LIST_ARGS:
# we want to list all available help entries
hdict_cmd = {}
for cmd in (cmd for cmd in cmdset if has_perm(caller, cmd, 'cmd')
if not cmd.key.startswith('__')
and not (hasattr(cmd, 'is_exit') and cmd.is_exit)):
if hdict_cmd.has_key(cmd.help_category):
hdict_cmd[cmd.help_category].append(cmd.key)
else:
hdict_cmd[cmd.help_category] = [cmd.key]
hdict_db = {}
for topic in (topic for topic in HelpEntry.objects.get_all_topics()
if has_perm(caller, topic, 'view')):
if hdict_db.has_key(topic.help_category):
hdict_db[topic.help_category].append(topic.key)
else:
hdict_db[topic.help_category] = [topic.key]
help_entry = format_help_list(hdict_cmd, hdict_db)
caller.msg(help_entry)
return
# Look for a particular help entry
# Cmd auto-help dynamic entries
cmdmatches = [cmd for cmd in cmdset
if query in cmd and has_perm(caller, cmd, 'cmd')]
if len(cmdmatches) > 1:
# multiple matches. Try to limit it down to exact match
exactmatches = [cmd for cmd in cmdmatches if cmd == query]
if exactmatches:
cmdmatches = exactmatches
# Help-database static entries
dbmatches = \
[topic for topic in
HelpEntry.objects.find_topicmatch(query, exact=False)
if has_perm(caller, topic, 'view')]
if len(dbmatches) > 1:
exactmatches = \
[topic for topic in
HelpEntry.objects.find_topicmatch(query, exact=True)
if has_perm(caller, topic, 'view')]
if exactmatches:
dbmatches = exactmatches
# Handle result
if (not cmdmatches) and (not dbmatches):
# no normal match. Check if this is a category match instead
categ_cmdmatches = [cmd.key for cmd in cmdset
if query == cmd.help_category and has_perm(caller, cmd, 'cmd')]
categ_dbmatches = \
[topic.key for topic in
HelpEntry.objects.find_topics_with_category(query)
if has_perm(caller, topic, 'view')]
cmddict = None
dbdict = None
if categ_cmdmatches:
cmddict = {query:categ_cmdmatches}
if categ_dbmatches:
dbdict = {query:categ_dbmatches}
if cmddict or dbdict:
help_entry = format_help_list(cmddict, dbdict)
else:
help_entry = "No help entry found for '%s'" % query
elif len(cmdmatches) == 1:
# we matched against a command name or alias. Show its help entry.
suggested = []
if dbmatches:
suggested = [entry.key for entry in dbmatches]
cmd = cmdmatches[0]
help_entry = format_help_entry(cmd.key, cmd.__doc__,
aliases=cmd.aliases,
suggested=suggested)
elif len(dbmatches) == 1:
# matched against a database entry
entry = dbmatches[0]
help_entry = format_help_entry(entry.key, entry.entrytext)
else:
# multiple matches of either type
cmdalts = [cmd.key for cmd in cmdmatches]
dbalts = [entry.key for entry in dbmatches]
helptext = "Multiple help entries match your search ..."
help_entry = format_help_entry("", helptext, None, cmdalts + dbalts)
# send result to user
caller.msg(help_entry)
class CmdSetHelp(MuxCommand):
"""
@help - edit the help database
Usage:
@help[/switches] <topic>[,category[,permission,permission,...]] = <text>
Switches:
add - add or replace a new topic with text.
append - add text to the end of topic with a newline between.
merge - As append, but don't add a newline between the old
text and the appended text.
delete - remove help topic.
force - (used with add) create help topic also if the topic
already exists.
Examples:
@sethelp/add throw = This throws something at ...
@sethelp/append pickpocketing,Thievery,is_thief, is_staff) = This steals ...
@sethelp/append pickpocketing, ,is_thief, is_staff) = This steals ...
"""
key = "@help"
aliases = "@sethelp"
permissions = "cmd:sethelp"
help_category = "Building"
def func(self):
"Implement the function"
caller = self.caller
switches = self.switches
lhslist = self.lhslist
rhs = self.rhs
if not self.rhs:
caller.msg("Usage: @sethelp/[add|del|append|merge] <topic>[,category[,permission,..] = <text>]")
return
topicstr = ""
category = ""
permissions = ""
try:
topicstr = lhslist[0]
category = lhslist[1]
permissions = ",".join(lhslist[2:])
except Exception:
pass
if not topicstr:
caller.msg("You have to define a topic!")
return
string = ""
print topicstr, category, permissions
if switches and switches[0] in ('append', 'app','merge'):
# add text to the end of a help topic
# find the topic to append to
old_entry = None
try:
old_entry = HelpEntry.objects.get(key=topicstr)
except Exception:
pass
if not old_entry:
string = "Could not find topic '%s'. You must give an exact name." % topicstr
else:
entrytext = old_entry.entrytext
if switches[0] == 'merge':
old_entry.entrytext = "%s %s" % (entrytext, self.rhs)
string = "Added the new text right after the old one (merge)."
else:
old_entry.entrytext = "%s\n\n%s" % (entrytext, self.rhs)
string = "Added the new text as a new paragraph after the old one (append)"
old_entry.save()
elif switches and switches[0] in ('delete','del'):
#delete a help entry
old_entry = None
try:
old_entry = HelpEntry.objects.get(key=topicstr)
except Exception:
pass
if not old_entry:
string = "Could not find topic. You must give an exact name."
else:
old_entry.delete()
string = "Deleted the help entry '%s'." % topicstr
else:
# add a new help entry.
force_create = ('for' in switches) or ('force' in switches)
old_entry = None
try:
old_entry = HelpEntry.objects.get(key=topicstr)
except Exception:
pass
if old_entry:
if force_create:
old_entry.key = topicstr
old_entry.entrytext = self.rhs
old_entry.help_category = category
old_entry.permissions = permissions
old_entry.save()
string = "Overwrote the old topic '%s' with a new one." % topicstr
else:
string = "Topic '%s' already exists. Use /force to overwrite it." % topicstr
else:
# no old entry. Create a new one.
new_entry = create.create_help_entry(topicstr,
rhs, category, permissions)
if new_entry:
string = "Topic '%s' was successfully created." % topicstr
else:
string = "Error when creating topic '%s'! Maybe it already exists?" % topicstr
# give feedback
caller.msg(string)