예제 #1
0
파일: system.py 프로젝트: AHecky3/evennia
def format_script_list(scripts):
    "Takes a list of scripts and formats the output."
    if not scripts:
        return "<No scripts>"

    table = EvTable("{wdbref{n", "{wobj{n", "{wkey{n", "{wintval{n", "{wnext{n",
                    "{wrept{n", "{wdb", "{wtypeclass{n", "{wdesc{n",
                    align='r', border="tablecols")
    for script in scripts:
        nextrep = script.time_until_next_repeat()
        if nextrep is None:
            nextrep = "PAUS" if script.db._paused_time else "--"
        else:
            nextrep = "%ss" % nextrep

        maxrepeat = script.repeats
        if maxrepeat:
            rept = "%i/%i" % (maxrepeat - script.remaining_repeats(), maxrepeat)
        else:
            rept = "-/-"

        table.add_row(script.id,
                      script.obj.key if (hasattr(script, 'obj') and script.obj) else "<Global>",
                      script.key,
                      script.interval if script.interval > 0 else "--",
                      nextrep,
                      rept,
                      "*" if script.persistent else "-",
                      script.typeclass_path.rsplit('.', 1)[-1],
                      crop(script.desc, width=20))
    return "%s" % table
예제 #2
0
파일: system.py 프로젝트: lulinqing/evennia
def format_script_list(scripts):
    "Takes a list of scripts and formats the output."
    if not scripts:
        return "<No scripts>"

    table = EvTable("{wdbref{n", "{wobj{n", "{wkey{n", "{wintval{n", "{wnext{n",
                    "{wrept{n", "{wdb", "{wtypeclass{n", "{wdesc{n",
                    align='r', border="tablecols")
    for script in scripts:
        nextrep = script.time_until_next_repeat()
        if nextrep is None:
            nextrep = "PAUS" if script.db._paused_time else "--"
        else:
            nextrep = "%ss" % nextrep

        maxrepeat = script.repeats
        if maxrepeat:
            rept = "%i/%i" % (maxrepeat - script.remaining_repeats(), maxrepeat)
        else:
            rept = "-/-"

        table.add_row(script.id,
                      script.obj.key if (hasattr(script, 'obj') and script.obj) else "<Global>",
                      script.key,
                      script.interval if script.interval > 0 else "--",
                      nextrep,
                      rept,
                      "*" if script.persistent else "-",
                      script.typeclass_path.rsplit('.', 1)[-1],
                      crop(script.desc, width=20))
    return "%s" % table
예제 #3
0
def _test():
    "test evform"
    form = EvForm("src.utils.evform_test")

    # add data to each tagged form cell
    form.map(cells={1: "{gTom the Bouncer{n",
                    2: "{yGriatch{n",
                    3: "A sturdy fellow",
                    4: 12,
                    5: 10,
                    6:  5,
                    7: 18,
                    8: 10,
                    9:  3})
    # create the EvTables
    tableA = EvTable("HP","MV","MP",
                               table=[["**"], ["*****"], ["***"]],
                               border="incols")
    tableB = EvTable("Skill", "Value", "Exp",
                               table=[["Shooting", "Herbalism", "Smithing"],
                                      [12,14,9],["550/1200", "990/1400", "205/900"]],
                               border="incols")
    # add the tables to the proper ids in the form
    form.map(tables={"A": tableA,
                     "B": tableB})

    # unicode is required since the example contains non-ascii characters
    print unicode(form)
    return form
예제 #4
0
파일: system.py 프로젝트: lulinqing/evennia
    def func(self):
        "List the players"

        caller = self.caller
        if self.args and self.args.is_digit():
            nlim = int(self.args)
        else:
            nlim = 10

        nplayers = PlayerDB.objects.count()

        # typeclass table
        dbtotals = PlayerDB.objects.object_totals()
        typetable = EvTable("{wtypeclass{n", "{wcount{n", "{w%%{n", border="cells", align="l")
        for path, count in dbtotals.items():
            typetable.add_row(path, count, "%.2f" % ((float(count) / nplayers) * 100))
        # last N table
        plyrs = PlayerDB.objects.all().order_by("db_date_created")[max(0, nplayers - nlim):]
        latesttable = EvTable("{wcreated{n", "{wdbref{n", "{wname{n", "{wtypeclass{n", border="cells", align="l")
        for ply in plyrs:
            latesttable.add_row(utils.datetime_format(ply.date_created), ply.dbref, ply.key, ply.typeclass.path)

        string = "\n{wPlayer typeclass distribution:{n\n%s" % typetable
        string += "\n{wLast %s Players created:{n\n%s" % (min(nplayers, nlim), latesttable)
        caller.msg(string)
예제 #5
0
파일: system.py 프로젝트: AHecky3/evennia
    def func(self):
        "List the players"

        caller = self.caller
        if self.args and self.args.is_digit():
            nlim = int(self.args)
        else:
            nlim = 10

        nplayers = PlayerDB.objects.count()

        # typeclass table
        dbtotals = PlayerDB.objects.object_totals()
        typetable = EvTable("{wtypeclass{n", "{wcount{n", "{w%%{n", border="cells", align="l")
        for path, count in dbtotals.items():
            typetable.add_row(path, count, "%.2f" % ((float(count) / nplayers) * 100))
        # last N table
        plyrs = PlayerDB.objects.all().order_by("db_date_created")[max(0, nplayers - nlim):]
        latesttable = EvTable("{wcreated{n", "{wdbref{n", "{wname{n", "{wtypeclass{n", border="cells", align="l")
        for ply in plyrs:
            latesttable.add_row(utils.datetime_format(ply.date_created), ply.dbref, ply.key, ply.typeclass.path)

        string = "\n{wPlayer typeclass distribution:{n\n%s" % typetable
        string += "\n{wLast %s Players created:{n\n%s" % (min(nplayers, nlim), latesttable)
        caller.msg(string)
예제 #6
0
    def func(self):
        "Setup the rss-channel mapping"

        # checking we have all we need
        if not settings.RSS_ENABLED:
            string = """RSS is not enabled. You need to activate it in game/settings.py."""
            self.msg(string)
            return
        try:
            import feedparser
            feedparser   # to avoid checker error of not being used
        except ImportError:
            string = ("RSS requires python-feedparser (https://pypi.python.org/pypi/feedparser). "
                      "Install before continuing.")
            self.msg(string)
            return

        if 'list' in self.switches:
            # show all connections
            rssbots = [bot.typeclass for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="rssbot-")]
            if rssbots:
                from src.utils.evtable import EvTable
                table = EvTable("{wdbid{n", "{wupdate rate{n", "{wev-channel", "{wRSS feed URL{n", border="cells", maxwidth=78)
                for rssbot in rssbots:
                    table.add_row(rssbot.id, rssbot.db.rss_rate, rssbot.db.ev_channel, rssbot.db.rss_url)
                self.caller.msg(table)
            else:
                self.msg("No rss bots found.")
            return

        if('disconnect' in self.switches or 'remove' in self.switches or
                                                    'delete' in self.switches):
            botname = "rssbot-%s" % self.lhs
            matches = PlayerDB.objects.filter(db_is_bot=True, db_key=botname)
            if not matches:
                # try dbref match
                matches = PlayerDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#"))
            if matches:
                matches[0].delete()
                self.msg("RSS connection destroyed.")
            else:
                self.msg("RSS connection/bot could not be removed, does it exist?")
            return

        if not self.args or not self.rhs:
            string = "Usage: @rss2chan[/switches] <evennia_channel> = <rss url>"
            self.msg(string)
            return
        channel = self.lhs
        url = self.rhs

        botname = "rssbot-%s" % url
        # create a new bot
        bot = PlayerDB.objects.filter(username__iexact=botname)
        if bot:
            # re-use existing bot
            bot = bot[0].typeclass
            if not bot.is_bot:
                self.msg("Player '%s' already exists and is not a bot." % botname)
                return
        else:
            bot = create.create_player(botname, None, None, typeclass=bots.RSSBot)
        bot.start(ev_channel=channel, rss_url=url, rss_rate=10)
        self.msg("RSS reporter created. Fetching RSS.")
예제 #7
0
    def func(self):
        "Setup the irc-channel mapping"

        if not settings.IRC_ENABLED:
            string = """IRC is not enabled. You need to activate it in game/settings.py."""
            self.msg(string)
            return

        if 'list' in self.switches:
            # show all connections
            ircbots = [bot.typeclass for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="ircbot-")]
            if ircbots:
                from src.utils.evtable import EvTable
                table = EvTable("{wdbid{n", "{wbotname{n", "{wev-channel{n", "{wirc-channel{n", maxwidth=78)
                for ircbot in ircbots:
                    ircinfo = "%s (%s:%s)" % (ircbot.db.irc_channel, ircbot.db.irc_network, ircbot.db.irc_port)
                    table.add_row(ircbot.id, ircbot.db.irc_botname, ircbot.db.ev_channel, ircinfo)
                self.caller.msg(table)
            else:
                self.msg("No irc bots found.")
            return


        if('disconnect' in self.switches or 'remove' in self.switches or
                                                    'delete' in self.switches):
            botname = "ircbot-%s" % self.lhs
            matches = PlayerDB.objects.filter(db_is_bot=True, db_key=botname)
            if not matches:
                # try dbref match
                matches = PlayerDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#"))
            if matches:
                matches[0].delete()
                self.msg("IRC connection destroyed.")
            else:
                self.msg("IRC connection/bot could not be removed, does it exist?")
            return

        if not self.args or not self.rhs:
            string = "Usage: @irc2chan[/switches] <evennia_channel> = <ircnetwork> <port> <#irchannel> <botname>"
            self.msg(string)
            return

        channel = self.lhs
        self.rhs = self.rhs.replace('#', ' ') # to avoid Python comment issues
        try:
            irc_network, irc_port, irc_channel, irc_botname = \
                       [part.strip() for part in self.rhs.split(None, 3)]
            irc_channel = "#%s" % irc_channel
        except Exception:
            string = "IRC bot definition '%s' is not valid." % self.rhs
            self.msg(string)
            return

        botname = "ircbot-%s" % irc_botname

        # create a new bot
        bot = PlayerDB.objects.filter(username__iexact=botname)
        if bot:
            # re-use an existing bot
            bot = bot[0].typeclass
            if not bot.is_bot:
                self.msg("Player '%s' already exists and is not a bot." % botname)
                return
        else:
            bot = create.create_player(botname, None, None, typeclass=bots.IRCBot)
        bot.start(ev_channel=channel, irc_botname=irc_botname, irc_channel=irc_channel,
                  irc_network=irc_network, irc_port=irc_port)
        self.msg("Connection created. Starting IRC bot.")
예제 #8
0
    def func(self):
        "Implement the command"

        caller = self.caller

        if self.args and self.args.isdigit():
            nlim = int(self.args)
        else:
            nlim = 10

        nobjs = ObjectDB.objects.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()
        nother = nobjs - nchars - nrooms - nexits

        nobjs = nobjs or 1  # fix zero-div error with empty database

        # total object sum table
        totaltable = EvTable("{wtype{n",
                             "{wcomment{n",
                             "{wcount{n",
                             "{w%%{n",
                             border="table",
                             align="l")
        totaltable.align = 'l'
        totaltable.add_row("Characters", "(BASE_CHARACTER_TYPECLASS)", nchars,
                           "%.2f" % ((float(nchars) / nobjs) * 100))
        totaltable.add_row("Rooms", "(location=None)", nrooms,
                           "%.2f" % ((float(nrooms) / nobjs) * 100))
        totaltable.add_row("Exits", "(destination!=None)", nexits,
                           "%.2f" % ((float(nexits) / nobjs) * 100))
        totaltable.add_row("Other", "", nother,
                           "%.2f" % ((float(nother) / nobjs) * 100))

        # typeclass table
        typetable = EvTable("{wtypeclass{n",
                            "{wcount{n",
                            "{w%%{n",
                            border="table",
                            align="l")
        typetable.align = 'l'
        dbtotals = ObjectDB.objects.object_totals()
        for path, count in dbtotals.items():
            typetable.add_row(path, count,
                              "%.2f" % ((float(count) / nobjs) * 100))

        # last N table
        objs = ObjectDB.objects.all().order_by(
            "db_date_created")[max(0, nobjs - nlim):]
        latesttable = EvTable("{wcreated{n",
                              "{wdbref{n",
                              "{wname{n",
                              "{wtypeclass{n",
                              align="l",
                              border="table")
        latesttable.align = 'l'
        for obj in objs:
            latesttable.add_row(utils.datetime_format(obj.date_created),
                                obj.dbref, obj.key, obj.typeclass.path)

        string = "\n{wObject subtype totals (out of %i Objects):{n\n%s" % (
            nobjs, totaltable)
        string += "\n{wObject typeclass distribution:{n\n%s" % typetable
        string += "\n{wLast %s Objects created:{n\n%s" % (min(
            nobjs, nlim), latesttable)
        caller.msg(string)
예제 #9
0
    def func(self):
        "Setup the rss-channel mapping"

        # checking we have all we need
        if not settings.RSS_ENABLED:
            string = """RSS is not enabled. You need to activate it in game/settings.py."""
            self.msg(string)
            return
        try:
            import feedparser
            feedparser  # to avoid checker error of not being used
        except ImportError:
            string = (
                "RSS requires python-feedparser (https://pypi.python.org/pypi/feedparser). "
                "Install before continuing.")
            self.msg(string)
            return

        if 'list' in self.switches:
            # show all connections
            rssbots = [
                bot.typeclass for bot in PlayerDB.objects.filter(
                    db_is_bot=True, username__startswith="rssbot-")
            ]
            if rssbots:
                from src.utils.evtable import EvTable
                table = EvTable("{wdbid{n",
                                "{wupdate rate{n",
                                "{wev-channel",
                                "{wRSS feed URL{n",
                                border="cells",
                                maxwidth=78)
                for rssbot in rssbots:
                    table.add_row(rssbot.id, rssbot.db.rss_rate,
                                  rssbot.db.ev_channel, rssbot.db.rss_url)
                self.caller.msg(table)
            else:
                self.msg("No rss bots found.")
            return

        if ('disconnect' in self.switches or 'remove' in self.switches
                or 'delete' in self.switches):
            botname = "rssbot-%s" % self.lhs
            matches = PlayerDB.objects.filter(db_is_bot=True, db_key=botname)
            if not matches:
                # try dbref match
                matches = PlayerDB.objects.filter(db_is_bot=True,
                                                  id=self.args.lstrip("#"))
            if matches:
                matches[0].delete()
                self.msg("RSS connection destroyed.")
            else:
                self.msg(
                    "RSS connection/bot could not be removed, does it exist?")
            return

        if not self.args or not self.rhs:
            string = "Usage: @rss2chan[/switches] <evennia_channel> = <rss url>"
            self.msg(string)
            return
        channel = self.lhs
        url = self.rhs

        botname = "rssbot-%s" % url
        # create a new bot
        bot = PlayerDB.objects.filter(username__iexact=botname)
        if bot:
            # re-use existing bot
            bot = bot[0].typeclass
            if not bot.is_bot:
                self.msg("Player '%s' already exists and is not a bot." %
                         botname)
                return
        else:
            bot = create.create_player(botname,
                                       None,
                                       None,
                                       typeclass=bots.RSSBot)
        bot.start(ev_channel=channel, rss_url=url, rss_rate=10)
        self.msg("RSS reporter created. Fetching RSS.")
예제 #10
0
    def func(self):
        "Setup the irc-channel mapping"

        if not settings.IRC_ENABLED:
            string = """IRC is not enabled. You need to activate it in game/settings.py."""
            self.msg(string)
            return

        if 'list' in self.switches:
            # show all connections
            ircbots = [
                bot.typeclass for bot in PlayerDB.objects.filter(
                    db_is_bot=True, username__startswith="ircbot-")
            ]
            if ircbots:
                from src.utils.evtable import EvTable
                table = EvTable("{wdbid{n",
                                "{wbotname{n",
                                "{wev-channel{n",
                                "{wirc-channel{n",
                                maxwidth=78)
                for ircbot in ircbots:
                    ircinfo = "%s (%s:%s)" % (ircbot.db.irc_channel,
                                              ircbot.db.irc_network,
                                              ircbot.db.irc_port)
                    table.add_row(ircbot.id, ircbot.db.irc_botname,
                                  ircbot.db.ev_channel, ircinfo)
                self.caller.msg(table)
            else:
                self.msg("No irc bots found.")
            return

        if ('disconnect' in self.switches or 'remove' in self.switches
                or 'delete' in self.switches):
            botname = "ircbot-%s" % self.lhs
            matches = PlayerDB.objects.filter(db_is_bot=True, username=botname)
            dbref = utils.dbref(self.lhs)
            if not matches and dbref:
                # try dbref match
                matches = PlayerDB.objects.filter(db_is_bot=True, id=dbref)
            if matches:
                matches[0].delete()
                self.msg("IRC connection destroyed.")
            else:
                self.msg(
                    "IRC connection/bot could not be removed, does it exist?")
            return

        if not self.args or not self.rhs:
            string = "Usage: @irc2chan[/switches] <evennia_channel> = <ircnetwork> <port> <#irchannel> <botname>"
            self.msg(string)
            return

        channel = self.lhs
        self.rhs = self.rhs.replace('#', ' ')  # to avoid Python comment issues
        try:
            irc_network, irc_port, irc_channel, irc_botname = \
                       [part.strip() for part in self.rhs.split(None, 3)]
            irc_channel = "#%s" % irc_channel
        except Exception:
            string = "IRC bot definition '%s' is not valid." % self.rhs
            self.msg(string)
            return

        botname = "ircbot-%s" % irc_botname

        # create a new bot
        bot = PlayerDB.objects.filter(username__iexact=botname)
        if bot:
            # re-use an existing bot
            bot = bot[0].typeclass
            if not bot.is_bot:
                self.msg("Player '%s' already exists and is not a bot." %
                         botname)
                return
        else:
            bot = create.create_player(botname,
                                       None,
                                       None,
                                       typeclass=bots.IRCBot)
        bot.start(ev_channel=channel,
                  irc_botname=irc_botname,
                  irc_channel=irc_channel,
                  irc_network=irc_network,
                  irc_port=irc_port)
        self.msg("Connection created. Starting IRC bot.")
예제 #11
0
파일: system.py 프로젝트: AHecky3/evennia
    def func(self):
        "Implement the command"

        caller = self.caller

        if self.args and self.args.isdigit():
            nlim = int(self.args)
        else:
            nlim = 10

        nobjs = ObjectDB.objects.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()
        nother = nobjs - nchars - nrooms - nexits

        nobjs = nobjs or 1 # fix zero-div error with empty database

        # total object sum table
        totaltable = EvTable("{wtype{n", "{wcomment{n", "{wcount{n", "{w%%{n", border="table", align="l")
        totaltable.align = 'l'
        totaltable.add_row("Characters", "(BASE_CHARACTER_TYPECLASS)", nchars, "%.2f" % ((float(nchars) / nobjs) * 100))
        totaltable.add_row("Rooms", "(location=None)", nrooms, "%.2f" % ((float(nrooms) / nobjs) * 100))
        totaltable.add_row("Exits", "(destination!=None)", nexits, "%.2f" % ((float(nexits) / nobjs) * 100))
        totaltable.add_row("Other", "", nother, "%.2f" % ((float(nother) / nobjs) * 100))

        # typeclass table
        typetable = EvTable("{wtypeclass{n", "{wcount{n", "{w%%{n", border="table", align="l")
        typetable.align = 'l'
        dbtotals = ObjectDB.objects.object_totals()
        for path, count in dbtotals.items():
            typetable.add_row(path, count, "%.2f" % ((float(count) / nobjs) * 100))

        # last N table
        objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim):]
        latesttable = EvTable("{wcreated{n", "{wdbref{n", "{wname{n", "{wtypeclass{n", align="l", border="table")
        latesttable.align = 'l'
        for obj in objs:
            latesttable.add_row(utils.datetime_format(obj.date_created),
                                obj.dbref, obj.key, obj.typeclass.path)

        string = "\n{wObject subtype totals (out of %i Objects):{n\n%s" % (nobjs, totaltable)
        string += "\n{wObject typeclass distribution:{n\n%s" % typetable
        string += "\n{wLast %s Objects created:{n\n%s" % (min(nobjs, nlim), latesttable)
        caller.msg(string)
예제 #12
0
    def _parse_rectangles(self, cellchar, tablechar, form, **kwargs):
        """
        Parse a form for rectangular formfields identified by
        formchar enclosing an identifier.
        """

        # update options given at creation with new input - this
        # allows e.g. self.map() to add custom settings for individual
        # cells/tables
        custom_options = copy.copy(self.options)
        custom_options.update(kwargs)

        nform = len(form)

        mapping = {}
        cell_coords = {}
        table_coords = {}

        # Locate the identifier tags and the horizontal end coords for all forms
        re_cellchar =  re.compile(r"%s+([^%s%s])%s+" % (cellchar, INVALID_FORMCHARS, cellchar, cellchar))
        re_tablechar = re.compile(r"%s+([^%s%s|])%s+" % (tablechar, INVALID_FORMCHARS, tablechar, tablechar))
        for iy, line in enumerate(_to_ansi(form, regexable=True)):
            # find cells
            ix0 = 0
            while True:
                match = re_cellchar.search(line, ix0)
                if match:
                    # get the width of the rectangle directly from the match
                    cell_coords[match.group(1)] = [iy, match.start(), match.end()]
                    ix0 = match.end()
                else:
                    break
            # find tables
            ix0 = 0
            while True:
                match = re_tablechar.search(line, ix0)
                if match:
                    # get the width of the rectangle directly from the match
                    table_coords[match.group(1)] = [iy, match.start(), match.end()]
                    ix0 = match.end()
                else:
                    break
        #print "cell_coords:", cell_coords
        #print "table_coords:", table_coords

        # get rectangles and assign EvCells
        for key, (iy, leftix, rightix) in cell_coords.items():

            # scan up to find top of rectangle
            dy_up = 0
            if iy > 0:
                for i in range(1,iy):
                    #print "dy_up:", [form[iy-i][ix] for ix in range(leftix, rightix)]
                    if all(form[iy-i][ix] == cellchar for ix in range(leftix, rightix)):
                        dy_up += 1
                    else:
                        break
            # find bottom edge of rectangle
            dy_down = 0
            if iy < nform-1:
                for i in range(1,nform-iy-1):
                    #print "dy_down:", [form[iy+i][ix]for ix in range(leftix, rightix)]
                    if all(form[iy+i][ix] == cellchar for ix in range(leftix, rightix)):
                        dy_down += 1
                    else:
                        break

            #  we have our rectangle. Calculate size of EvCell.
            iyup = iy - dy_up
            iydown = iy + dy_down
            width = rightix - leftix
            height = abs(iyup - iydown) + 1

            # we have all the coordinates we need. Create EvCell.
            data = self.cells_mapping.get(key, "")
            #if key == "1":
            #    print "creating cell '%s' (%s):" % (key, data)
            #    print "iy=%s, iyup=%s, iydown=%s, leftix=%s, rightix=%s, width=%s, height=%s" % (iy, iyup, iydown, leftix, rightix, width, height)

            options = { "pad_left":0, "pad_right":0, "pad_top":0, "pad_bottom":0, "align":"l", "valign":"t", "enforce_size":True}
            options.update(custom_options)
            #if key=="4":
            #print "options:", options

            mapping[key] = (iyup, leftix, width, height, EvCell(data, width=width, height=height,**options))

        # get rectangles and assign Tables
        for key, (iy, leftix, rightix) in table_coords.items():

            # scan up to find top of rectangle
            dy_up = 0
            if iy > 0:
                for i in range(1,iy):
                    #print "dy_up:", [form[iy-i][ix] for ix in range(leftix, rightix)]
                    if all(form[iy-i][ix] == tablechar for ix in range(leftix, rightix)):
                        dy_up += 1
                    else:
                        break
            # find bottom edge of rectangle
            dy_down = 0
            if iy < nform-1:
                for i in range(1,nform-iy-1):
                    #print "dy_down:", [form[iy+i][ix]for ix in range(leftix, rightix)]
                    if all(form[iy+i][ix] == tablechar for ix in range(leftix, rightix)):
                        dy_down += 1
                    else:
                        break

            #  we have our rectangle. Calculate size of Table.
            iyup = iy - dy_up
            iydown = iy + dy_down
            width = rightix - leftix
            height = abs(iyup - iydown) + 1

            # we have all the coordinates we need. Create Table.
            table = self.tables_mapping.get(key, None)
            #print "creating table '%s' (%s):" % (key, data)
            #print "iy=%s, iyup=%s, iydown=%s, leftix=%s, rightix=%s, width=%s, height=%s" % (iy, iyup, iydown, leftix, rightix, width, height)

            options = { "pad_left":0, "pad_right":0, "pad_top":0, "pad_bottom":0,
                        "align":"l", "valign":"t", "enforce_size":True}
            options.update(custom_options)
            #print "options:", options

            if table:
                table.reformat(width=width, height=height, **options)
            else:
                table = EvTable(width=width, height=height, **options)
            mapping[key] = (iyup, leftix, width, height, table)

        return mapping