From 7b43c4a608b1dfd8735af1e877e327e198090791 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 21 Apr 2011 10:29:24 +0000 Subject: [PATCH] Added @cset command for changing a channel's access restriction settings. Added @cboot and a few more missing channel commands. Cleaned out the utils commands and fixed formatting on a few default commands. --- src/commands/cmdsethandler.py | 14 +- src/commands/default/building.py | 35 +- src/commands/default/cmdset_default.py | 11 +- src/commands/default/comms.py | 444 +++++++++++-------------- src/commands/default/general.py | 34 +- src/commands/default/system.py | 10 +- src/commands/default/utils.py | 101 ------ src/utils/utils.py | 27 +- 8 files changed, 265 insertions(+), 411 deletions(-) delete mode 100644 src/commands/default/utils.py diff --git a/src/commands/cmdsethandler.py b/src/commands/cmdsethandler.py index 19c4bf2a5a..216666d293 100644 --- a/src/commands/cmdsethandler.py +++ b/src/commands/cmdsethandler.py @@ -163,6 +163,7 @@ class CmdSetHandler(object): "Display current commands" string = "" + merged = False if len(self.cmdset_stack) > 1: # We have more than one cmdset in stack; list them all num = 0 @@ -174,18 +175,19 @@ class CmdSetHandler(object): mergetype = "%s^" % (mergetype) string += "\n %i: <%s (%s, prio %i)>: %s" % \ (snum, cmdset.key, mergetype, - cmdset.priority, cmdset) - string += "\n (combining %i cmdsets):" % (num+1) - else: - string += "\n " + cmdset.priority, cmdset) + string += "\n" + merged = True # Display the currently active cmdset mergetype = self.mergetype_stack[-1] if mergetype != self.current.mergetype: merged_on = self.cmdset_stack[-2].key mergetype = "custom %s on %s" % (mergetype, merged_on) - string += " <%s (%s)> %s" % (self.current.key, - mergetype, self.current) + if merged: + string += " : %s" % (mergetype, self.current) + else: + string += " <%s (%s)>: %s" % (self.current.key, mergetype, self.current) return string.strip() def update(self, init_mode=False): diff --git a/src/commands/default/building.py b/src/commands/default/building.py index f260895dc3..bd475243d0 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -1414,18 +1414,6 @@ class CmdExamine(ObjManipCommand): locks = "cmd:perm(examine) or perm(Builders)" help_category = "Building" - def crop_line(self, text, heading="", line_width=79): - """ - Crops a line of text, adding [...] if doing so. - - heading + text + eventual [...] will not exceed line_width. - """ - headlen = len(str(heading)) - textlen = len(str(text)) - if textlen > (line_width - headlen): - text = "%s[...]" % text[:line_width - headlen - 5] - return text - def format_attributes(self, obj, attrname=None, crop=True): """ Helper function that returns info about attributes and/or @@ -1447,15 +1435,15 @@ class CmdExamine(ObjManipCommand): if db_attr and db_attr[0]: #self.caller.msg(db_attr) string += "\n{wPersistent attributes{n:" - for attr, value in db_attr: + for attr, value in db_attr: if crop: - value = self.crop_line(value, attr) + value = utils.crop(value) string += "\n %s = %s" % (attr, value) if ndb_attr and ndb_attr[0]: string += "\n{wNon-persistent attributes{n:" for attr, value in ndb_attr: if crop: - value = self.crop_line(value, attr) + value = utils.crop(value) string += "\n %s = %s" % (attr, value) return string @@ -1465,12 +1453,15 @@ class CmdExamine(ObjManipCommand): returns a string. """ - - string = "\n{wName/key{n: %s (#%i)" % (obj.name, obj.id) + + if obj.has_player: + string = "\n{wName/key{n: {c%s{n (%s)" % (obj.name, obj.dbref) + else: + string = "\n{wName/key{n: {C%s{n (%s)" % (obj.name, obj.dbref) if obj.aliases: string += "\n{wAliases{n: %s" % (", ".join(obj.aliases)) if obj.has_player: - string += "\n{wPlayer{n: %s" % obj.player.name + string += "\n{wPlayer{n: {c%s{n" % obj.player.name perms = obj.player.permissions if obj.player.is_superuser: perms = [""] @@ -1487,9 +1478,11 @@ class CmdExamine(ObjManipCommand): string += "\n{wPermissions{n: %s" % (", ".join(perms)) locks = str(obj.locks) if locks: - string += "\n{wLocks{n: %s" % ("; ".join([lock for lock in locks.split(';')])) + string += "\n{wLocks{n:" + utils.fill("; ".join([lock for lock in locks.split(';')]), indent=6) + if not (len(obj.cmdset.all()) == 1 and obj.cmdset.current.key == "Empty"): - string += "\n{wCurrent Cmdset (before permission checks){n:\n %s" % obj.cmdset + cmdsetstr = "\n".join([utils.fill(cmdset, indent=2) for cmdset in str(obj.cmdset).split("\n")]) + string += "\n{wCurrent Cmdset (before permission checks){n:\n %s" % cmdsetstr if obj.scripts.all(): string += "\n{wScripts{n:\n %s" % obj.scripts # add the attributes @@ -1514,7 +1507,7 @@ class CmdExamine(ObjManipCommand): string += "\n{wContents{n: " + ", ".join([cont.name for cont in obj.contents if cont not in exits and cont not in pobjs]) #output info - return "-"*50 + '\n' + string.strip() + "\n" + '-'*50 + return "-"*78 + '\n' + string.strip() + "\n" + '-'*78 def func(self): "Process command" diff --git a/src/commands/default/cmdset_default.py b/src/commands/default/cmdset_default.py index 9d0b24e46c..d4ae6552de 100644 --- a/src/commands/default/cmdset_default.py +++ b/src/commands/default/cmdset_default.py @@ -3,7 +3,7 @@ This module ties together all the commands of the default command set. """ from src.commands.cmdset import CmdSet from src.commands.default import general, help, admin, system -from src.commands.default import utils, comms, building +from src.commands.default import comms, building from src.commands.default import batchprocess class DefaultCmdSet(CmdSet): @@ -87,6 +87,10 @@ class DefaultCmdSet(CmdSet): self.add(comms.CmdChannels()) self.add(comms.CmdCdestroy()) self.add(comms.CmdChannelCreate()) + self.add(comms.CmdCset()) + self.add(comms.CmdCBoot()) + self.add(comms.CmdCemit()) + self.add(comms.CmdCWho()) self.add(comms.CmdCdesc()) self.add(comms.CmdPage()) self.add(comms.CmdIRC2Chan()) @@ -97,8 +101,3 @@ class DefaultCmdSet(CmdSet): # Batchprocessor commands self.add(batchprocess.CmdBatchCommands()) self.add(batchprocess.CmdBatchCode()) - - # Testing/Utility commands - self.add(utils.CmdTest()) - #self.add(utils.CmdTestPerms()) - self.add(utils.TestCom()) diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index 920dfd3ca6..d073d32493 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -16,6 +16,9 @@ def find_channel(caller, channelname, silent=False): """ channels = Channel.objects.channel_search(channelname) if not channels: + channels = [chan for chan in Channel.objects.all() if channelname in chan.aliases] + if channels: + return channels[0] if not silent: caller.msg("Channel '%s' not found." % channelname) return None @@ -223,7 +226,7 @@ class CmdChannels(MuxCommand): key = "@channels" aliases = ["@clist", "channels", "comlist", "chanlist", "channellist", "all channels"] help_category = "Comms" - locks = "cmd:all()" + locks = "cmd: not perm(channel_banned)" def func(self): "Implement function" @@ -291,7 +294,7 @@ class CmdCdestroy(MuxCommand): key = "@cdestroy" help_category = "Comms" - locks = "cmd:all()" + locks = "cmd: not perm(channel_banned)" def func(self): "Destroy objects cleanly." @@ -315,226 +318,146 @@ class CmdCdestroy(MuxCommand): CHANNELHANDLER.update() caller.msg("%s was destroyed." % channel) +class CmdCBoot(MuxCommand): + """ + @cboot + + Usage: + @cboot[/quiet] = [:reason] + + Switches: + quiet - don't notify the channel + + Kicks a player or object from a channel you control. + + """ + + key = "@cboot" + locks = "cmd: not perm(channel_banned)" + help_category = "Comms" + + def func(self): + "implement the function" -## def cmd_cset(self): -## """ -## @cset - -## Sets various flags on a channel. -## """ -## # TODO: Implement cmd_cset -## pass - -## def cmd_ccharge(self): -## """ -## @ccharge - -## Sets the cost to transmit over a channel. Default is free. -## """ -## # TODO: Implement cmd_ccharge -## pass - -## def cmd_cboot(self): -## """ -## @cboot - -## Usage: -## @cboot[/quiet] = - -## Kicks a player or object from a channel you control. -## """ -## caller = self.caller -## args = self.args -## switches = self.self_switches - -## if not args or not "=" in args: -## caller.msg("Usage: @cboot[/quiet] = ") -## return -## cname, objname = args.split("=",1) -## cname, objname = cname.strip(), objname.strip() -## if not cname or not objname: -## caller.msg("You must supply both channel and object.") -## return -## try: -## channel = CommChannel.objects.get(name__iexact=cname) -## except CommChannel.DoesNotExist: -## caller.msg("Could not find channel %s." % cname) -## return - -## #do we have power over this channel? -## if not channel.controlled_by(caller) or caller.has_perm("channels.channel_admin"): -## caller.msg("You don't have that power in channel '%s'." % cname) -## return - -## #mux specification requires an * before player objects. -## player_boot = False -## if objname[0] == '*': -## player_boot = True -## objname = objname[1:] -## bootobj = Object.objects.player_name_search(objname) -## if not bootobj: -## caller.msg("Object '%s' not found." % objname) -## return -## if bootobj.is_player() and not player_boot: -## caller.msg("To boot players you need to start their name with an '*'. ") -## return - -## #check so that this object really is on the channel in the first place -## membership = bootobj.channel_membership_set.filter(channel__name__iexact=cname) -## if not membership: -## caller.msg("'%s' is not on channel '%s'." % (objname,cname)) -## return - -## #announce to channel -## if not 'quiet' in switches: -## comsys.send_cmessage(cname, "%s boots %s from channel." % \ -## (caller.get_name(show_dbref=False), objname)) - -## #all is set, boot the object by removing all its aliases from the channel. -## for mship in membership: -## comsys.plr_del_channel(bootobj, mship.user_alias) - -## GLOBAL_CMD_TABLE.add_self("@cboot", cmd_cboot, help_category="Comms") - - -## def cmd_cemit(self): -## """ -## @cemit - send a message to channel - -## Usage: -## @cemit = -## @cemit/noheader = -## @cemit/sendername = - -## Allows the user to send a message over a channel as long as -## they own or control it. It does not show the user's name unless they -## provide the /sendername switch. - -## [[channel_selfs]] - -## Useful channel selfs -## (see their help pages for detailed help and options) - -## - Listing channels -## clist - show all channels available to you -## comlist - show channels you listen to - -## - Joining/parting channels -## addcom - add your alias for a channel -## delcom - remove alias for channel -## (leave channel if no more aliases) -## allcom - view, on/off or remove all your channels -## clearcom - removes all channels - -## - Other -## who - list who's online -## off - silence channel temporarily -## on - turn silenced channel back on -## """ -## caller = self.caller - -## if not self.args: -## caller.msg("@cemit[/switches] = ") -## return - -## eq_args = self.args.split('=', 1) - -## if len(eq_args) != 2: -## caller.msg("You must provide a channel name and a message to emit.") -## return - -## cname = eq_args[0].strip() -## cmessage = eq_args[1].strip() -## final_cmessage = cmessage -## if len(cname) == 0: -## caller.msg("You must provide a channel name to emit to.") -## return -## if len(cmessage) == 0: -## caller.msg("You must provide a message to emit.") -## return - -## name_matches = comsys.cname_search(cname, exact=True) -## if name_matches: -## cname_parsed = name_matches[0].get_name() -## else: -## caller.msg("Could not find channel %s." % (cname,)) -## return - -## # If this is False, don't show the channel header before -## # the message. For example: [Public] Woohoo! -## show_channel_header = True -## if "noheader" in self.self_switches: -## if not caller.has_perm("objects.emit_commchannel"): -## caller.msg(defines_global.NOPERMS_MSG) -## return -## final_cmessage = cmessage -## show_channel_header = False -## else: -## if "sendername" in self.self_switches: -## if not comsys.plr_has_channel(self.session, cname_parsed, -## return_muted=False): -## caller.msg("You must be on %s to do that." % (cname_parsed,)) -## return -## final_cmessage = "%s: %s" % (caller.get_name(show_dbref=False), -## cmessage) -## else: -## if not caller.has_perm("objects.emit_commchannel"): -## caller.msg(defines_global.NOPERMS_MSG) -## return -## final_cmessage = cmessage - -## if not "quiet" in self.self_switches: -## caller.msg("Sent - %s" % (name_matches[0],)) -## comsys.send_cmessage(cname_parsed, final_cmessage, -## show_header=show_channel_header) - -## #pipe to external channels (IRC, IMC) eventually mapped to this channel -## comsys.send_cexternal(cname_parsed, cmessage, caller=caller) - -## GLOBAL_CMD_TABLE.add_self("@cemit", cmd_cemit,priv_tuple=("channels.emit_commchannel",), -## help_category="Comms") - -## def cmd_cwho(self): -## """ -## @cwho - -## Usage: -## @cwho channel[/all] - -## Displays the name, status and object type for a given channel. -## Adding /all after the channel name will list disconnected players -## as well. -## """ -## session = self.session -## caller = self.caller - -## if not self.args: -## cmd_clist(self) -## caller.msg("Usage: @cwho [/all]") -## return - -## channel_name = self.args - -## if channel_name.strip() == '': -## caller.msg("You must specify a channel name.") -## return - -## name_matches = comsys.cname_search(channel_name, exact=True) - -## if name_matches: -## # Check to make sure the user has permission to use @cwho. -## is_channel_admin = caller.has_perm("objects.channel_admin") -## is_controlled_by_plr = name_matches[0].controlled_by(caller) + if not self.args or not self.rhs: + string = "Usage: @cboot[/quiet] = [:reason]" + self.caller.msg(string) + return -## if is_controlled_by_plr or is_channel_admin: -## comsys.msg_cwho(caller, channel_name) -## else: -## caller.msg("Permission denied.") -## return -## else: -## caller.msg("No channel with that name was found.") -## return -## GLOBAL_CMD_TABLE.add_self("@cwho", cmd_cwho, help_category="Comms") + channel = find_channel(self.caller, self.lhs) + if not channel: + return + reason = "" + player = None + if ":" in self.rhs: + playername, reason = self.rhs.rsplit(":", 1) + player = self.caller.search("*%s" % playername.lstrip('*')) + if not player: + player = self.caller.search("*%s" % self.rhs.lstrip('*')) + if not player: + return + if reason: + reason = " (reason: %s)" % reason + if not channel.access(self.caller, "control"): + string = "You don't control this channel." + self.caller.msg(string) + return + if not PlayerChannelConnection.objects.has_connection(player, channel): + string = "Player %s is not connected to channel %s." % (player.key, channel.key) + self.caller.msg(string) + return + if not "quiet" in self.switches: + string = "%s boots %s from channel.%s" % (self.caller, player.key, reason) + channel.msg(string) + # find all player's nicks linked to this channel and delete them + for nick in [nick for nick in player.character.nicks.get(nick_type="channel") + if nick.db_real.lower() == channel.key]: + nick.delete() + # disconnect player + channel.disconnect_from(player) + +class CmdCemit(MuxCommand): + """ + @cemit - send a message to channel + + Usage: + @cemit[/switches] = + + Switches: + noheader - don't show the [channel] header before the message + sendername - attach the sender's name before the message + quiet - don't echo the message back to sender + + Allows the user to broadcast a message over a channel as long as + they control it. It does not show the user's name unless they + provide the /sendername switch. + + """ + + key = "@cemit" + aliases = ["@cmsg"] + locks = "cmd: not perm(channel_banned)" + help_category = "Comms" + + def func(self): + "Implement function" + + if not self.args or not self.rhs: + string = "Usage: @cemit[/switches] = " + self.caller.msg(string) + return + channel = find_channel(self.caller, self.lhs) + if not channel: + return + if not channel.access(self.caller, "control"): + string = "You don't control this channel." + self.caller.msg(string) + return + message = self.rhs + if "sendername" in self.switches: + message = "%s: %s" % (self.caller.key, message) + if not "noheader" in self.switches: + message = "[%s] %s" % (channel.key, message) + channel.msg(message) + if not "quiet" in self.switches: + string = "Sent to channel %s: %s" % (channel.key, message) + self.caller.msg(string) + +class CmdCWho(MuxCommand): + """ + @cwho + + Usage: + @cwho + + List who is connected to a given channel you have access to. + """ + key = "@cwho" + locks = "cmd: not perm(channel_banned)" + help_category = "Comms" + + def func(self): + "implement function" + + if not self.args: + string = "Usage: @cwho " + self.caller.msg(string) + return + + channel = find_channel(self.caller, self.lhs) + if not channel: + return + if not channel.access(self.caller, "listen"): + string = "You can't access this channel." + self.caller.msg(string) + string = "\n{CChannel subscriptions{n" + string += "\n{w%s:{n\n" % channel.key + conns = PlayerChannelConnection.objects.get_all_connections(channel) + if conns: + string += " " + ", ".join([conn.player.key for conn in conns]) + else: + string += " " + self.caller.msg(string.strip()) class CmdChannelCreate(MuxCommand): """ @@ -583,47 +506,50 @@ class CmdChannelCreate(MuxCommand): caller.msg("Created channel %s and connected to it." % new_chan.key) -## def cmd_cchown(self): -## """ -## @cchown +class CmdCset(MuxCommand): + """ + @cset - changes channel access restrictions + + Usage: + @cset [= ] -## Usage: -## @cchown = + Changes the lock access restrictions of a channel. If no + lockstring was given, view the current lock definitions. + """ -## Changes the owner of a channel. -## """ -## caller = self.caller -## args = self.args -## if not args or "=" not in args: -## caller.msg("Usage: @cchown = ") -## return -## cname, pname = args.split("=",1) -## cname, pname = cname.strip(), pname.strip() -## #locate channel -## try: -## channel = CommChannel.objects.get(name__iexact=cname) -## except CommChannel.DoesNotExist: -## caller.msg("Channel '%s' not found." % cname) -## return -## #check so we have ownership to give away. -## if not channel.controlled_by(caller) and not caller.has_perm("channels.channel_admin"): -## caller.msg("You don't control this channel.") -## return -## #find the new owner -## new_owner = Object.objects.player_name_search(pname) -## if not new_owner: -## caller.msg("New owner '%s' not found." % pname) -## return -## old_owner = channel.get_owner() -## old_pname = old_owner.get_name(show_dbref=False) -## if old_owner == new_owner: -## caller.msg("Owner unchanged.") -## return -## #all is set, change owner -## channel.set_owner(new_owner) -## caller.msg("Owner of %s changed from %s to %s." % (cname, old_pname, pname)) -## new_owner.msg("%s transfered ownership of channel '%s' to you." % (old_pname, cname)) -## GLOBAL_CMD_TABLE.add_self("@cchown", cmd_cchown, help_category="Comms") + key = "@cset" + locks = "cmd:not perm(channel_banned)" + aliases = ["@cclock"] + help_category = "Comms" + + def func(self): + "run the function" + + if not self.args: + string = "Usage: @cset channel [= lockstring]" + self.caller.msg(string) + return + + channel = find_channel(self.caller, self.lhs) + if not channel: + return + if not self.rhs: + # no =, so just view the current locks + string = "Current locks on %s:" % channel.key + string = "%s\n %s" % (string, channel.locks) + self.caller.msg(string) + return + # we want to add/change a lock. + if not channel.access(self.caller, "control"): + string = "You don't control this channel." + self.caller.msg(string) + return + # Try to add the lock + channel.locks.add(self.rhs) + string = "Lock(s) applied. " + string += "Current locks on %s:" % channel.key + string = "%s\n %s" % (string, channel.locks) + self.caller.msg(string) class CmdCdesc(MuxCommand): diff --git a/src/commands/default/general.py b/src/commands/default/general.py index 348de2378c..d2f0157c8d 100644 --- a/src/commands/default/general.py +++ b/src/commands/default/general.py @@ -213,10 +213,24 @@ class CmdInventory(MuxCommand): locks = "cmd:all()" def func(self): - "hook function" - string = "You are carrying:" - for item in self.caller.contents: - string += "\n %s" % item.name + "check inventory" + items = self.caller.contents + if not items: + string = "You are not carrying anything." + else: + # format item list into nice collumns + cols = [[],[]] + for item in items: + cols[0].append(item.name) + desc = utils.crop(item.db.desc) + if not desc: + desc = "" + cols[1].append(desc) + # auto-format the columns to make them evenly wide + ftable = utils.format_table(cols) + string = "You are carrying:" + for row in ftable: + string += "\n " + "{C%s{n - %s" % (row[0], row[1]) self.caller.msg(string) class CmdGet(MuxCommand): @@ -552,8 +566,16 @@ class CmdAccess(MuxCommand): hierarchy_full = settings.PERMISSION_HIERARCHY string = "\n{wPermission Hierarchy{n (climbing):\n %s" % ", ".join(hierarchy_full) hierarchy = [p.lower() for p in hierarchy_full] + + if self.caller.player.is_superuser: + cperms = "" + pperms = "" + else: + cperms = ", ".join(caller.permissions) + pperms = ", ".join(caller.player.permissions) + string += "\n{wYour access{n:" - string += "\nCharacter %s: %s" % (caller.key, ", ".join(caller.permissions)) + string += "\nCharacter {c%s{n: %s" % (caller.key, cperms) if hasattr(caller, 'player'): - string += "\nPlayer %s: %s" % (caller.player.key, ", ".join(caller.player.permissions)) + string += "\nPlayer {c%s{n: %s" % (caller.player.key, pperms) caller.msg(string) diff --git a/src/commands/default/system.py b/src/commands/default/system.py index bd90279ff8..1f772648a3 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -270,14 +270,14 @@ class CmdObjects(MuxCommand): nplayers = PlayerDB.objects.count() nobjs = ObjectDB.objects.count() - base_typeclass = settings.BASE_CHARACTER_TYPECLASS - nchars = ObjectDB.objects.filter(db_typeclass_path=base_typeclass).count() - nrooms = ObjectDB.objects.filter(db_location__isnull=True).exclude(db_typeclass_path=base_typeclass).count() + base_char_typeclass = settings.BASE_CHARACTER_TYPECLASS + nchars = ObjectDB.objects.filter(db_typeclass_path=base_char_typeclass).count() + nrooms = ObjectDB.objects.filter(db_location__isnull=True).exclude(db_typeclass_path=base_char_typeclass).count() nexits = ObjectDB.objects.filter(db_location__isnull=False, db_destination__isnull=False).count() string += "\n{wPlayers:{n %i" % nplayers string += "\n{wObjects:{n %i" % nobjs - string += "\n{w Characters (base type):{n %i" % nchars + string += "\n{w Characters (BASE_CHARACTER_TYPECLASS):{n %i" % nchars string += "\n{w Rooms (location==None):{n %i" % nrooms string += "\n{w Exits (destination!=None):{n %i" % nexits string += "\n{w Other:{n %i\n" % (nobjs - nchars - nrooms - nexits) @@ -579,8 +579,6 @@ class CmdServerLoad(MuxCommand): caller.msg(string) - -#TODO - expand @ps as we add irc/imc2 support. class CmdPs(MuxCommand): """ list processes diff --git a/src/commands/default/utils.py b/src/commands/default/utils.py deleted file mode 100644 index 4498ab12c0..0000000000 --- a/src/commands/default/utils.py +++ /dev/null @@ -1,101 +0,0 @@ -""" -This defines some test commands for use while testing the MUD and its components. - -""" - -from django.conf import settings -from django.db import IntegrityError -from src.comms.models import Msg -from src.utils import create, debug, utils -from src.commands.default.muxcommand import MuxCommand - -from src.commands import cmdsethandler - - -# Test permissions - -class CmdTest(MuxCommand): - """ - test the command system - - Usage: - @test - - This command will echo back all argument or switches - given to it, showcasing the muxcommand style. - """ - - key = "@test" - aliases = ["@te", "@test all"] - help_category = "Utils" - locks = "cmd:perm(Wizards)" - - # the muxcommand class itself handles the display - # so we just defer to it by not adding any function. - - def func(self): - - def test(): - li = [] - for l in range(10000): - li.append(l) - self.caller.msg(li[-1]) - return "This is the return text" - #print 1/0 - def succ(f): - self.caller.msg("This is called after successful completion. Return value: %s" % f) - def err(e): - self.caller.msg("An error was encountered... %s" % e) - - #self.caller.msg("printed before call to sync run ...") - #test() - #self.caller.msg("after after call to sync run...") - - self.caller.msg("printed before call to async run ...") - utils.run_async(test, at_return=succ, at_err=err) - self.caller.msg("printed after call to async run ...") - - #cmdsetname = "game.gamesrc.commands.default.cmdset_default.DefaultCmdSet" - #self.caller.msg(cmdsethandler.CACHED_CMDSETS) - #cmdsethandler.import_cmdset(cmdsetname, self, self) - #self.caller.msg("Imported %s" % cmdsetname) - #self.caller.msg(cmdsethandler.CACHED_CMDSETS) - -class TestCom(MuxCommand): - """ - Test the command system - - Usage: - @testcom/create/list [channel] - """ - key = "@testcom" - locks = "cmd:perm(Wizards)" - help_category = "Utils" - def func(self): - "Run the test program" - caller = self.caller - - if 'create' in self.switches: - if self.args: - chankey = self.args - try: - channel = create.create_channel(chankey) - except IntegrityError: - caller.msg("Channel '%s' already exists." % chankey) - return - channel.connect_to(caller) - caller.msg("Created new channel %s" % chankey) - msgobj = create.create_message(caller.player, - "First post to new channel!") - channel.msg(msgobj) - - return - elif 'list' in self.switches: - msgresults = Msg.objects.get_messages_by_sender(caller) - string = "\n".join(["%s %s: %s" % (msg.date_sent, - [str(chan.key) for chan in msg.channels.all()], - msg.message) - for msg in msgresults]) - caller.msg(string) - return - caller.msg("Usage: @testcom/create channel") diff --git a/src/utils/utils.py b/src/utils/utils.py index 15df4fc95c..529f01ee8d 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -10,7 +10,6 @@ import datetime import random from twisted.internet import threads from django.conf import settings -from src.utils import ansi ENCODINGS = settings.ENCODINGS @@ -32,16 +31,33 @@ def is_iter(iterable): # except TypeError: # return False -def fill(text, width=78): +def fill(text, width=78, indent=0): """ Safely wrap text to a certain number of characters. text: (str) The text to wrap. width: (int) The number of characters to wrap to. + indent: (int) How much to indent new lines (the first line + will not be indented) """ if not text: return "" - return textwrap.fill(str(text), width) + indent = " " * indent + return textwrap.fill(str(text), width, subsequent_indent=indent) + + +def crop(text, width=78, suffix="[...]"): + """ + Crop text to a certain width, adding suffix to show the line + continues. Cropping will be done so that the suffix will also fit + within the given width. + """ + ltext = len(str(text)) + if ltext <= width: + return text + else: + lsuffix = len(suffix) + return text[:width-lsuffix] + suffix def dedent(text): """ @@ -353,10 +369,9 @@ def format_table(table, extra_space=1): if not table: return [[]] - max_widths = [max([len(str(val)) - for val in col]) for col in table] + max_widths = [max([len(str(val)) for val in col]) for col in table] ftable = [] - for irow in range(len(table[0])): + for irow in range(len(table[0])): ftable.append([str(col[irow]).ljust(max_widths[icol]) + " " * extra_space for icol, col in enumerate(table)]) return ftable