mirror of
https://github.com/evennia/evennia.git
synced 2026-04-04 23:17:17 +02:00
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:
parent
a3917073ff
commit
72d40285b8
61 changed files with 381 additions and 184 deletions
297
src/commands/default/help.py
Normal file
297
src/commands/default/help.py
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue