Fixed mudform unicode issues and expanded docs.

This commit is contained in:
Griatch 2014-02-01 17:01:15 +01:00
parent f3f96af23a
commit 62dc119296
2 changed files with 139 additions and 63 deletions

View file

@ -15,78 +15,149 @@ object when displaying the form.
Example of input file testform.py: Example of input file testform.py:
FORMCHAR = "x"
CELLCHAR = "x"
TABLECHAR = "c" TABLECHAR = "c"
FORM = ''' FORM = '''
.-------------------------------------. .------------------------------------------------.
/ \ | |
| Name: xxx1xxxx Player: xxxxx2xxxxx | | Name: xxxxx1xxxxx Player: xxxxxxx2xxxxxxx |
| | | xxxxxxxxxxx |
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< | |
| Desc: xxxxxxxxxxx Str:x4x Dex:x5x | >----------------------------------------------<
| xxxxx3xxxxx Int:x6x Sta:x7x | | |
| xxxxxxxxxxx Luc:x8x Mag:x9x | | Desc: xxxxxxxxxxx STR: x4x DEX: x5x |
| | | xxxxx3xxxxx INT: x6x STA: x7x |
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< | xxxxxxxxxxx LUC: x8x MAG: x9x |
| | | |
| Skills: | >----------------------------------------------<
| ccccccccccccccccccccccccccccccccccccc | | | |
| ccccccccccccccccccccccccccccccccccccc | | cccccccc | ccccccccccccccccccccccccccccccccccc |
| ccccccccccccccccccccccccccccccccccccc | | cccccccc | ccccccccccccccccccccccccccccccccccc |
| | | cccAcccc | ccccccccccccccccccccccccccccccccccc |
`--------------------------------------´ | cccccccc | ccccccccccccccccccccccccccccccccccc |
| cccccccc | cccccccccccccccccBccccccccccccccccc |
| | |
`-----------------------------------------------´
''' '''
The first line of the FORM string is ignored. The first line of the FORM string is ignored. The forms and table
markers must mark out complete, unbroken rectangles, each containing
one embedded single-character identifier (so the smallest element
possible is a 3-character wide form). The identifier can be any
character except for the FORM_CHAR and TABLE_CHAR and some of the
common ascii-art elements, like space, _ | * etc (see
INVALID_FORMCHARS in this module). Form Rectangles can have any size,
but must be separated from each other by at least one other
character's width.
Use as follows: Use as follows:
MudForm("path/to/testform.py") import mudform
# create a new form from the template
form = mudform.MudForm("path/to/testform.py")
By marking out rectangles, this area gets reserved for the Cell. # add data to each tagged form cell
Embedded inside each area must be a one-character identifier to tag form.map(cells={1: "Tom the Bouncer",
the area (so the smallest form size is 3 characters including the 2: "Griatch",
marker). This marker is any character except the designated formchar 3: "A sturdy fellow",
("x" in this case). Rectangles can have any size, but must be 4: 12,
separated from each other by at least one other character's width. 5: 10,
6: 5,
7: 18,
8: 10,
9: 3})
# create the MudTables
tableA = mudform.MudTable("HP","MV","MP",
table=[["**"], ["*****"], ["***"]],
border="incols")
tableB = mudform.MudTable("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}
print form
Parsing this file will result in a CharMap object. This is This produces the following result:
primed with a dictionary of {<tag>:function} where the function
is responsible for producing a string for each form location. The .------------------------------------------------.
Cell in each location will enforce the size given by the template | |
and will crop too-long text. | Name: Tom the Player: Griatch |
| Bouncer |
| |
>----------------------------------------------<
| |
| Desc: A sturdy STR: 12 DEX: 10 |
| fellow INT: 5 STA: 18 |
| LUC: 10 MAG: 3 |
| |
>----------------------------------------------<
| | |
| HP|MV|MP | Skill |Value |Exp |
| ~~+~~+~~ | ~~~~~~~~~~~+~~~~~~~~~~~+~~~~~~~~~~~ |
| **|**|** | Shooting |12 |550/1200 |
| |**|* | Herbalism |14 |990/1400 |
| |* | | Smithing |9 |205/900 |
| | |
------------------------------------------------
The marked forms have been replaced with Cells of text and with
MudTables. The form can be updated by simply re-applying form.map()
with the updated data.
When working with the template ascii file, you can use form.reload()
to re-read the template and re-apply all existing mappings.
Each component is restrained to the width and height specified by the
template, so it will resize to fit (or crop text if the area is too
small for it. If you try to fit a table into an area it cannot fit
into (when including its borders and at least one line of text), the
form will raise an error.
""" """
import re import re
import copy import copy
from src.utils.mudtable import Cell, MudTable from src.utils.mudtable import Cell, MudTable
from src.utils.utils import all_from_module from src.utils.utils import all_from_module, to_str, to_unicode
# non-valid form-identifying characters (which can thus be # non-valid form-identifying characters (which can thus be
# used as separators between forms without being detected # used as separators between forms without being detected
# as an identifier). These should be listed in regex form. # as an identifier). These should be listed in regex form.
INVALID_FORMCHARS = r"\s\-\|\*\#\<\>\~\^" INVALID_FORMCHARS = r"\s\/\|\\\*\_\-\#\<\>\~\^\:\;\.\,"
class MudForm(object): class MudForm(object):
""" """
This object is instantiated with a text file and parses This object is instantiated with a text file and parses
it for rectangular form fields. It can then be fed a it for rectangular form fields. It can then be fed a
mapping so as to populate the fields with fixed-width mapping so as to populate the fields with fixed-width
Cell objects for displaying Cell or Tablets.
"""
def __init__(self, filename, cells=None, tables=None, **kwargs):
""" """
Read the template file and parse it for formfields def __init__(self, filename=None, cells=None, tables=None, form=None, **kwargs):
"""
Initiate the form
keywords:
filename - path to template file
form - dictionary of {"CELLCHAR":char,
"TABLECHAR":char,
"FORM":templatestring}
if this is given, filename is not read.
cells - a dictionary mapping of {id:text}
tables - dictionary mapping of {id:MudTable}
other kwargs are fed as options to the Cells and MudTablets
(see mudtablet.Cell and mudtablet.MudTablet for more info).
kwargs:
<identifier> - text for fill into form
""" """
self.filename = filename self.filename = filename
self.input_form_dict = form
self.cells_mapping = dict((str(key), value) for key, value in cells.items()) if cells else {} self.cells_mapping = dict((str(key), value) for key, value in cells.items()) if cells else {}
self.tables_mapping = dict((str(key), value) for key, value in tables.items()) if tables else {} self.tables_mapping = dict((str(key), value) for key, value in tables.items()) if tables else {}
@ -144,12 +215,11 @@ class MudForm(object):
match = re_tablechar.search(line, ix0) match = re_tablechar.search(line, ix0)
if match: if match:
# get the width of the rectangle directly from the match # get the width of the rectangle directly from the match
print "table.match:", match.group(), match.group(1)
table_coords[match.group(1)] = [iy, match.start(), match.end()] table_coords[match.group(1)] = [iy, match.start(), match.end()]
ix0 = match.end() ix0 = match.end()
else: else:
break break
print "table_coords:", table_coords #print "table_coords:", table_coords
# get rectangles and assign Cells # get rectangles and assign Cells
for key, (iy, leftix, rightix) in cell_coords.items(): for key, (iy, leftix, rightix) in cell_coords.items():
@ -222,15 +292,13 @@ class MudForm(object):
# we have all the coordinates we need. Create Table. # we have all the coordinates we need. Create Table.
table = self.tables_mapping.get(key, None) table = self.tables_mapping.get(key, None)
#if key == "1": #print "creating table '%s' (%s):" % (key, data)
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)
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, options = { "pad_left":0, "pad_right":0, "pad_top":0, "pad_bottom":0,
"align":"l", "valign":"t", "enforce_size":True} "align":"l", "valign":"t", "enforce_size":True}
options.update(custom_options) options.update(custom_options)
#if key=="4": #print "options:", options
print "options:", options
if table: if table:
table.reformat(width=width, height=height, **options) table.reformat(width=width, height=height, **options)
@ -258,22 +326,26 @@ class MudForm(object):
""" """
Add mapping for form. Add mapping for form.
keywords: cells - a dictionary of {identifier:celltext}
<identifier> - text tables - a dictionary of {identifier:table}
kwargs will be forwarded to tables/cells. See
mudtable.Cell and mudtable.MudTable for info.
""" """
# clean kwargs (these cannot be overridden) # clean kwargs (these cannot be overridden)
kwargs.pop("enforce_size", None) kwargs.pop("enforce_size", None)
kwargs.pop("width", None) kwargs.pop("width", None)
kwargs.pop("height", None) kwargs.pop("height", None)
new_cells = dict((str(key), value) for key, value in cells.items()) if cells else {} new_cells = dict((to_str(key), value) for key, value in cells.items()) if cells else {}
new_tables = dict((str(key), value) for key, value in tables.items()) if tables else {} new_tables = dict((to_str(key), value) for key, value in tables.items()) if tables else {}
self.cells_mapping.update(new_cells) self.cells_mapping.update(new_cells)
self.tables_mapping.update(new_tables) self.tables_mapping.update(new_tables)
self.reload() self.reload()
def reload(self, filename=None, **kwargs): def reload(self, filename=None, form=None, **kwargs):
""" """
Creates the form from a stored file name Creates the form from a stored file name
""" """
@ -282,19 +354,23 @@ class MudForm(object):
kwargs.pop("width", None) kwargs.pop("width", None)
kwargs.pop("height", None) kwargs.pop("height", None)
if filename: if form or self.input_form_dict:
datadict = form if form else self.input_form_dict
self.input_form_dict = datadict
elif filename or self.filename:
filename = filename if filename else self.filename
datadict = all_from_module(filename)
self.filename = filename self.filename = filename
filename = self.filename else:
datadict = {}
datadict = all_from_module(filename) cellchar = to_str(datadict.get("FORMCHAR", "x"))
self.cellchar = to_str(cellchar[0] if len(cellchar) > 1 else cellchar)
cellchar = datadict.get("CELLCHAR", "x")
self.cellchar = cellchar[0] if len(cellchar) > 1 else cellchar
tablechar = datadict.get("TABLECHAR", "c") tablechar = datadict.get("TABLECHAR", "c")
self.tablechar = tablechar[0] if len(tablechar) > 1 else tablechar self.tablechar = tablechar[0] if len(tablechar) > 1 else tablechar
# split into a list of list of lines. Form can be indexed with form[iy][ix] # split into a list of list of lines. Form can be indexed with form[iy][ix]
self.raw_form = datadict.get("FORM", "").split("\n") self.raw_form = to_unicode(datadict.get("FORM", "")).split("\n")
# strip first line # strip first line
self.raw_form = self.raw_form[1:] if self.raw_form else self.raw_form self.raw_form = self.raw_form[1:] if self.raw_form else self.raw_form
@ -306,6 +382,6 @@ class MudForm(object):
def __str__(self): def __str__(self):
"Prints the form" "Prints the form"
return "\n".join(self.form) return "\n".join([to_str(line) for line in self.form])

View file

@ -790,7 +790,7 @@ class MudTable(object):
# calculate actual table width/height in characters # calculate actual table width/height in characters
self.cwidth = sum(cwidths) self.cwidth = sum(cwidths)
self.cheight = sum(cheights) self.cheight = sum(cheights)
print "actual table width, height:", self.cwidth, self.cheight, self.width, self.height #print "actual table width, height:", self.cwidth, self.cheight, self.width, self.height
def _generate_lines(self): def _generate_lines(self):
""" """