""" 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 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] [,category[,permission,permission,...]] = 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] [,category[,permission,..] = ]") 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)