Reworked EvTable to use internal EvColumn objects. This allows a new method on EvTable. Columns with a set width will not be affected by auto-balancing, allowing for mixing fixed and auto-balancing columns as suggested in #550. Changed EvTable keywords involving characters to consistently end with _char, such as corner_top_left -> corner_top_left_char.

This commit is contained in:
Griatch 2014-10-02 09:08:08 +02:00
parent fd7bb29505
commit 8b8fbe8101
2 changed files with 247 additions and 109 deletions

View file

@ -1,11 +1,6 @@
# coding=utf-8
"""
Mudform - a way to create advanced ascii forms
WARNING: UNDER DEVELOPMENT. Evform does currently NOT support
colour ANSI markers in the table. Non-colour forms should
work fully (so make issues if they don't).
EvForm - a way to create advanced ascii forms
This is intended for creating advanced ascii game forms, such as a
large pretty character sheet or info document.
@ -14,7 +9,7 @@ The system works on the basis of a readin template that is given in a
separate python file imported into the handler. This file contains
some optional settings and a string mapping out the form. The template
has markers in it to denounce fields to fill. The markers map the
absolute size of the field and will be filled with an evtable.Cell
absolute size of the field and will be filled with an evtable.EvCell
object when displaying the form.
Note, when printing examples with ANSI color, you need to wrap
@ -119,7 +114,7 @@ This produces the following result:
| | |
------------------------------------------------
The marked forms have been replaced with Cells of text and with
The marked forms have been replaced with EvCells of text and with
EvTables. The form can be updated by simply re-applying form.map()
with the updated data.
@ -136,7 +131,7 @@ form will raise an error.
import re
import copy
from src.utils.evtable import Cell, EvTable
from src.utils.evtable import EvCell, EvTable
from src.utils.utils import all_from_module, to_str, to_unicode
from src.utils.ansi import ANSIString
@ -160,7 +155,7 @@ class EvForm(object):
This object is instantiated with a text file and parses
it for rectangular form fields. It can then be fed a
mapping so as to populate the fields with fixed-width
Cell or Tablets.
EvCell or Tablets.
"""
def __init__(self, filename=None, cells=None, tables=None, form=None, **kwargs):
@ -176,8 +171,8 @@ class EvForm(object):
cells - a dictionary mapping of {id:text}
tables - dictionary mapping of {id:EvTable}
other kwargs are fed as options to the Cells and EvTables
(see evtablet.Cell and evtable.EvTable for more info).
other kwargs are fed as options to the EvCells and EvTables
(see evtablet.EvCell and evtable.EvTable for more info).
"""
self.filename = filename
@ -246,7 +241,7 @@ class EvForm(object):
#print "cell_coords:", cell_coords
#print "table_coords:", table_coords
# get rectangles and assign Cells
# get rectangles and assign EvCells
for key, (iy, leftix, rightix) in cell_coords.items():
# scan up to find top of rectangle
@ -268,13 +263,13 @@ class EvForm(object):
else:
break
# we have our rectangle. Calculate size of Cell.
# 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 Cell.
# 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)
@ -285,7 +280,7 @@ class EvForm(object):
#if key=="4":
#print "options:", options
mapping[key] = (iyup, leftix, width, height, Cell(data, width=width, height=height,**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():
@ -355,7 +350,7 @@ class EvForm(object):
tables - a dictionary of {identifier:table}
kwargs will be forwarded to tables/cells. See
evtable.Cell and evtable.EvTable for info.
evtable.EvCell and evtable.EvTable for info.
"""
# clean kwargs (these cannot be overridden)
@ -441,3 +436,4 @@ def _test():
# unicode is required since the example contains non-ascii characters
print unicode(form)
return form

View file

@ -30,15 +30,17 @@ Result:
| This is a single row | | | |
+----------------------+----------+---+--------------------------+
As seen, the table will automatically expand with empty cells to
make the table symmetric.
As seen, the table will automatically expand with empty cells to make
the table symmetric.
Tables can be restricted to a given width.
table.reformat(width=50, align="l")
(We could just have added these keywords to the table
creation call) yields the following result:
(We could just have added these keywords to the table creation call)
This yields the following result:
+-----------+------------+-----------+-----------+
| Heading1 | Heading2 | | |
+~~~~~~~~~~~+~~~~~~~~~~~~+~~~~~~~~~~~+~~~~~~~~~~~+
@ -57,23 +59,45 @@ creation call) yields the following result:
| row | | | |
+-----------+------------+-----------+-----------+
When adding new rows/columns their data can have its
own alignments (left/center/right, top/center/bottom).
Table-columns can be individually formatted. Note that if an
individual column is set with a specific width, table auto-balancing
will not affect this column (this may lead to the full table being too
wide, so be careful mixing fixed-width columns with auto- balancing).
Here we change the width and alignment of the column at index 3
(Python starts from 0):
If the height is restricted, cells will be restricted
from expanding vertically. This will lead to text
contents being cropped. Each cell can only shrink
to a minimum width and height of 1.
table.reformat_column(3, width=30, align="r")
print table
+-----------+-------+-----+-----------------------------+---------+
| Heading1 | Headi | | | |
| | ng2 | | | |
+~~~~~~~~~~~+~~~~~~~+~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~+
| 1 | 4 | 7 | This is long data | Test1 |
+-----------+-------+-----+-----------------------------+---------+
| 2 | 5 | 8 | This is even longer data | Test3 |
+-----------+-------+-----+-----------------------------+---------+
| 3 | 6 | 9 | | Test4 |
+-----------+-------+-----+-----------------------------+---------+
| This is a | | | | |
| single | | | | |
| row | | | | |
+-----------+-------+-----+-----------------------------+---------+
It is intended to be used with ANSIString for supporting
When adding new rows/columns their data can have its own alignments
(left/center/right, top/center/bottom).
If the height is restricted, cells will be restricted from expanding
vertically. This will lead to text contents being cropped. Each cell
can only shrink to a minimum width and height of 1.
EvTable is intended to be used with ANSIString for supporting
ANSI-coloured string types.
When a cell is auto-wrapped across multiple lines,
ANSI-reset sequences will be put at the end of each
wrapped line. This means that the colour of a wrapped
cell will not "bleed", but it also means that eventual
colour outside
When a cell is auto-wrapped across multiple lines, ANSI-reset
sequences will be put at the end of each wrapped line. This means that
the colour of a wrapped cell will not "bleed", but it also means that
eventual colour outside
"""
#from textwrap import wrap
@ -241,9 +265,9 @@ def fill(text, width=70, **kwargs):
w = ANSITextWrapper(width=width, **kwargs)
return w.fill(text)
# Cell class (see further down for the EvTable itself)
# EvCell class (see further down for the EvTable itself)
class Cell(object):
class EvCell(object):
"""
Holds a single data cell for the table. A cell has a certain width
and height and contains one or more lines of data. It can shrink
@ -287,11 +311,6 @@ class Cell(object):
border_top - top border width
border_bottom - bottom border width
crop_string - string to use when cropping sideways,
default is '[...]'
crop - crop content of cell rather than expand vertically,
default=False
border_char - this will use a single border char for all borders.
overruled by individual settings below
border_left_char - char used for left border
@ -302,10 +321,16 @@ class Cell(object):
corner_char - character used when two borders cross.
(default is ""). This is overruled by
individual settings below.
corner_top_left
corner_top_right
corner_bottom_left
corner_bottom_right
corner_top_left_char - char used for "nw" corner
corner_top_right_char - char used for "nw" corner
corner_bottom_left_char - char used for "sw" corner
corner_bottom_right_char - char used for "se" corner
crop_string - string to use when cropping sideways,
default is '[...]'
crop - crop content of cell rather than expand vertically,
default=False
enforce_size - if true, the width/height of the
cell is strictly enforced and
@ -352,11 +377,11 @@ class Cell(object):
self.border_top_char = kwargs.get("border_topchar", borderchar if borderchar else "-")
self.border_bottom_char = kwargs.get("border_bottom_char", borderchar if borderchar else "-")
corner = kwargs.get("corner_char", "+")
self.corner_top_left = kwargs.get("corner_top_left", corner)
self.corner_top_right = kwargs.get("corner_top_right", corner)
self.corner_bottom_left = kwargs.get("corner_bottom_left", corner)
self.corner_bottom_right = kwargs.get("corner_bottom_right", corner)
corner_char = kwargs.get("corner_char", "+")
self.corner_top_left_char = kwargs.get("corner_top_left_char", corner_char)
self.corner_top_right_char = kwargs.get("corner_top_right_char", corner_char)
self.corner_bottom_left_char = kwargs.get("corner_bottom_left_char", corner_char)
self.corner_bottom_right_char = kwargs.get("corner_bottom_right_char", corner_char)
# alignments
self.align = kwargs.get("align", "l")
@ -504,14 +529,14 @@ class Cell(object):
cwidth = self.width + self.pad_left + self.pad_right + \
max(0,self.border_left-1) + max(0, self.border_right-1)
vfill = self.corner_top_left if left else ""
vfill = self.corner_top_left_char if left else ""
vfill += cwidth * self.border_top_char
vfill += self.corner_top_right if right else ""
vfill += self.corner_top_right_char if right else ""
top = [vfill for i in range(self.border_top)]
vfill = self.corner_bottom_left if left else ""
vfill = self.corner_bottom_left_char if left else ""
vfill += cwidth * self.border_bottom_char
vfill += self.corner_bottom_right if right else ""
vfill += self.corner_bottom_right_char if right else ""
bottom = [vfill for i in range(self.border_bottom)]
return top + [left + line + right for line in data] + bottom
@ -552,7 +577,7 @@ class Cell(object):
def reformat(self, **kwargs):
"""
Reformat the Cell with new options
Reformat the EvCell with new options
kwargs:
as the class __init__
"""
@ -590,11 +615,11 @@ class Cell(object):
self.border_top_char = kwargs.get("border_topchar", borderchar if borderchar else self.border_top_char)
self.border_bottom_char = kwargs.get("border_bottom_char", borderchar if borderchar else self.border_bottom_char)
corner = kwargs.get("corner_char", None)
self.corner_top_left = kwargs.get("corner_top_left", corner if corner is not None else self.corner_top_left)
self.corner_top_right = kwargs.get("corner_top_right", corner if corner is not None else self.corner_top_right)
self.corner_bottom_left = kwargs.get("corner_bottom_left", corner if corner is not None else self.corner_bottom_left)
self.corner_bottom_right = kwargs.get("corner_bottom_right", corner if corner is not None else self.corner_bottom_right)
corner_char = kwargs.get("corner_char", None)
self.corner_top_left_char = kwargs.get("corner_top_left", corner_char if corner_char is not None else self.corner_top_left_char)
self.corner_top_right_char = kwargs.get("corner_top_right", corner_char if corner_char is not None else self.corner_top_right_char)
self.corner_bottom_left_char = kwargs.get("corner_bottom_left", corner_char if corner_char is not None else self.corner_bottom_left_char)
self.corner_bottom_right_char = kwargs.get("corner_bottom_right", corner_char if corner_char is not None else self.corner_bottom_right_char)
# fill all other properties
for key, value in kwargs.items():
@ -621,6 +646,9 @@ class Cell(object):
"""
return self.formatted
def __repr__(self):
return ANSIString("EvCel<%s>" % self.formatted)
def __str__(self):
"returns cell contents on string form"
return ANSIString("\n").join(self.formatted)
@ -630,14 +658,107 @@ class Cell(object):
return unicode(ANSIString("\n").join(self.formatted))
## EvColumn class
class EvColumn(object):
"""
Column class
This class holds a list of Cells to represent a column of a table.
It holds operations and settings that affect *all* cells in the
column.
Columns are not intended to be used stand-alone; they should be
incorporated into an EvTable (like EvCells)
"""
def __init__(self, *args, **kwargs):
"""
Args:
Data for each row in the column
Keywords:
width - If set, this column will be hardcoded to have
this width, regardless of the length of data in
each individual cell. The cells will adjust
or not depending on other settings. The
EvTable will not be allowed to auto-adjust
the width of EvColumns with their width set.
All EvCell keywords are available, these settings
will be applied to every Cell in the column.
"""
self.width = kwargs.get("width", None)
self.options = kwargs
self.column = [EvCell(data, **kwargs) for data in args]
self._normalize_width()
def _normalize_width(self):
"""
Make sure to adjust the width of all cells so we form
a coherent and lined-up column.
"""
col = self.column
noptions = copy(self.options)
# use fixed width or adjust to the largest cell
noptions["width"] = self.width or noptions.get("width") or max(cell.get_width() for cell in col) if col else 0
[cell.reformat(**noptions) for cell in col]
def add_rows(self, *args, **kwargs):
"""
Add new cells to column. They will be inserted as
a series of rows. It will inherit the options
of the rest of the column's cells (use update to change
options).
Args:
data for the new cells
Keywords:
ypos - index position in table before which to insert the
new column. Uses Python indexing, so to insert at the top,
use ypos=0. If not given, data will be inserted at the end
of the column.
"""
ypos = kwargs.get("ypos", None)
if ypos is None or ypos > len(self.column):
# add to the end
self.column.extend([EvCell(data, **self.options) for data in args])
else:
# insert cells before given index
ypos = min(len(self.column)-1, max(0, int(ypos)))
new_cells = [EvCell(data, **self.options) for data in args]
self.column = self.column[:ypos] + new_cells + self.column[ypos:]
self._normalize_width()
def reformat(self, force_width=False, **kwargs):
"""
Change the options for the collumn. Will not change width unless
the force_width keyword is passed (this is only sent by the
EvTable.reformat_column() method)
"""
self.width = kwargs.get("width", self.width) if force_width else self.width
self.options.update(kwargs)
self._normalize_width()
def __repr__(self):
return "EvColumn<%i cels>" % len(self.column)
def __len__(self):
return len(self.column)
def __iter__(self):
return iter(self.column)
def __getitem__(self, index):
return self.column[index]
def __setitem__(self, index, value):
self.column[index] = value
def __delitem__(self, index):
del self.column[index]
## Main Evtable class
class EvTable(object):
"""
Table class.
This table implements an ordered grid of Cells, with
all cell boundaries lining up.
The table contains of a list of EvColumns, each consisting of EvCells so
that the result is a 2D matrix.
"""
def __init__(self, *args, **kwargs):
@ -646,7 +767,7 @@ class EvTable(object):
headers for the table
Keywords:
table - list of columns (list of lists) for seeding
table - list of columns (lists of lists, or lists of EvColumns) for seeding
the table. If not given, the table will start
out empty
header - True/False - turn off header being treated
@ -667,11 +788,11 @@ class EvTable(object):
corners. Default is 1.
corner_char - character to use in corners when border is
active.
corner_top_left - character to use in upper left corner of table
corner_top_left_char - character to use in upper left corner of table
(defaults to corner_char)
corner_top_right
corner_bottom_left
corner_bottom_right
corner_top_right_char
corner_bottom_left_char
corner_bottom_right_char
pretty_corners - (default True): use custom characters to make
the table corners look "rounded". Uses UTF-8
characters.
@ -701,16 +822,16 @@ class EvTable(object):
to each cell in the table.
"""
# table itself is a 2D grid - a list of columns
# at this point table is a 2D grid - a list of columns
# x is the column position, y the row
self.table = kwargs.pop("table", [])
table = kwargs.pop("table", [])
# header is a list of texts. We merge it to the table's top
header = list(args)
self.header = header != []
if self.header:
if self.table:
excess = len(header) - len(self.table)
if table:
excess = len(header) - len(table)
if excess > 0:
# header bigger than table
self.table.extend([] for i in range(excess))
@ -718,9 +839,9 @@ class EvTable(object):
# too short header
header.extend(_to_ansi(["" for i in range(abs(excess))]))
for ix, heading in enumerate(header):
self.table[ix].insert(0, heading)
table[ix].insert(0, heading)
else:
self.table = [[heading] for heading in header]
table = [[heading] for heading in header]
# even though we inserted the header, we can still turn off
# header border underling etc. We only allow this if a header
# was actually set
@ -740,10 +861,10 @@ class EvTable(object):
self.border_width = kwargs.get("border_width", 1)
self.corner_char = kwargs.get("corner_char", "+")
pcorners = kwargs.pop("pretty_corners", False)
self.corner_top_left = _to_ansi(kwargs.pop("corner_top_left", '.' if pcorners else self.corner_char))
self.corner_top_right = _to_ansi(kwargs.pop("corner_top_right", '.' if pcorners else self.corner_char))
self.corner_bottom_left = _to_ansi(kwargs.pop("corner_bottom_left", ' ' if pcorners else self.corner_char))
self.corner_bottom_right = _to_ansi(kwargs.pop("corner_bottom_right", ' ' if pcorners else self.corner_char))
self.corner_top_left_char = _to_ansi(kwargs.pop("corner_top_left_char", '.' if pcorners else self.corner_char))
self.corner_top_right_char = _to_ansi(kwargs.pop("corner_top_right_char", '.' if pcorners else self.corner_char))
self.corner_bottom_left_char = _to_ansi(kwargs.pop("corner_bottom_left_char", ' ' if pcorners else self.corner_char))
self.corner_bottom_right_char = _to_ansi(kwargs.pop("corner_bottom_right_char", ' ' if pcorners else self.corner_char))
self.width = kwargs.pop("width", None)
self.height = kwargs.pop("height", None)
@ -760,9 +881,9 @@ class EvTable(object):
# save options
self.options = kwargs
if self.table:
# generate the table on the fly
self.table = [[Cell(data, **kwargs) for data in col] for col in self.table]
# use the temporary table to generate the table on the fly, as a list of EvColumns.
# If the input is not iterable we assume it is an EvColumn.
self.table = [col if isinstance(col, EvColumn) else EvColumn(*col, **kwargs) for col in table]
# this is the actual working table
self.worktable = None
@ -784,13 +905,13 @@ class EvTable(object):
def corners(ret):
"Handle corners of table"
if ix == 0 and iy == 0:
ret["corner_top_left"] = self.corner_top_left
ret["corner_top_left_char"] = self.corner_top_left_char
if ix == nx and iy == 0:
ret["corner_top_right"] = self.corner_top_right
ret["corner_top_right_char"] = self.corner_top_right_char
if ix == 0 and iy == ny:
ret["corner_bottom_left"] = self.corner_bottom_left
ret["corner_bottom_left_char"] = self.corner_bottom_left_char
if ix == nx and iy == ny:
ret["corner_bottom_right"] = self.corner_bottom_right
ret["corner_bottom_right_char"] = self.corner_bottom_right_char
return ret
def left_edge(ret):
@ -885,15 +1006,15 @@ class EvTable(object):
self.worktable = deepcopy(self.table)
options = copy(self.options)
# balance number of rows
# balance number of rows to make a rectangular table
ncols = len(self.worktable)
nrows = [len(col) for col in self.worktable]
nrowmax = max(nrows) if nrows else 0
for icol, nrow in enumerate(nrows):
if nrow < nrowmax:
# add more rows
self.worktable[icol].extend([Cell("", **self.options) for i in range(nrowmax-nrow)])
# add more rows to too-short columns
empty_rows = ["" for i in range(nrowmax-nrow)]
self.worktable[icol].add_rows(*empty_rows)
self.ncols = ncols
self.nrows = nrowmax
@ -938,12 +1059,11 @@ class EvTable(object):
# reformat worktable (for width align)
for ix, col in enumerate(self.worktable):
for iy, cell in enumerate(col):
try:
cell.reformat(width=cwidths[ix], **options)
except Exception, e:
msg = "ix=%s, iy=%s, width=%s: %s" % (ix, iy, cwidths[ix], e.message)
raise Exception ("Error in horizontal allign:\n %s" % msg)
try:
col.reformat(width=cwidths[ix], **options)
except Exception, e:
msg = "ix=%s, width=%s: %s" % (ix, cwidths[ix], e.message)
raise #Exception ("Error in horizontal allign:\n %s" % msg)
# equalize heights for each row (we must do this here, since it may have changed to fit new widths)
cheights = [max(cell.get_height() for cell in (col[iy] for col in self.worktable)) for iy in range(nrowmax)]
@ -1031,6 +1151,9 @@ class EvTable(object):
empty rows in the other columns. If too few,
the new column with get new empty rows. All
filling rows are added to the end.
Args:
Either a single EvColumn instance or
a number of data to be used to create a new column
keyword-
header - the header text for the column
xpos - index position in table before which
@ -1043,25 +1166,30 @@ class EvTable(object):
options = dict(self.options.items() + kwargs.items())
xpos = kwargs.get("xpos", None)
column = [Cell(data, **options) for data in args]
if args and isinstance(args[0], EvColumn):
column = args[0]
else:
column = EvColumn(*args, **options)
htable = self.nrows
excess = self.ncols - htable
if excess > 0:
# we need to add new rows to table
for col in self.table:
col.extend([Cell("", **options) for i in range(excess)])
empty_rows = ["" for i in range(excess)]
col.add_rows(*empty_rows, **options)
elif excess < 0:
# we need to add new rows to new column
column.extend([Cell("", **options) for i in range(abs(excess))])
empty_rows = ["" for i in range(abs(excess))]
column.add_rows(*empty_rows, **options)
header = kwargs.get("header", None)
if header:
column.insert(0, Cell(unicode(header), **options))
column.add_rows(unicode(header), ypos=0, **options)
self.header = True
elif self.header:
# we have a header already. Offset
column.insert(0, Cell("", **options))
column.add_rows("", ypos=0, **options)
if xpos is None or xpos > len(self.table) - 1:
# add to the end
self.table.append(column)
@ -1085,32 +1213,33 @@ class EvTable(object):
input new row. If not given, will be added
to the end. Uses Python indexing (so first row is
ypos=0)
See Cell class for other keyword arguments
See EvCell class for other keyword arguments
"""
# this will replace default options with new ones without changing default
row = list(args)
options = dict(self.options.items() + kwargs.items())
ypos = kwargs.get("ypos", None)
row = [Cell(data, **options) for data in args]
htable = len(self.table[0]) if len(self.table)>0 else 0 # assuming balanced table
excess = len(row) - len(self.table)
if excess > 0:
# we need to add new empty columns to table
self.table.extend([[Cell("", **options) for i in range(htable)] for k in range(excess)])
empty_rows = ["" for i in range(htable)]
self.table.extend([EvColumn(*empty_rows, **options) for i in range(excess)])
elif excess < 0:
# we need to add more cells to row
row.extend([Cell("", **options) for i in range(abs(excess))])
row.extend(["" for i in range(abs(excess))])
if ypos is None or ypos > htable - 1:
# add new row to the end
for icol, col in enumerate(self.table):
col.append(row[icol])
col.add_rows(row[icol], **options)
else:
# insert row elsewhere
ypos = min(htable-1, max(0, int(ypos)))
for icol, col in enumerate(self.table):
col.insert(ypos, row[icol])
col.add_rows(row[icol], ypos=ypos, **options)
self._balance()
def reformat(self, **kwargs):
@ -1124,20 +1253,30 @@ class EvTable(object):
hchar = kwargs.pop("header_line_char", self.header_line_char)
# border settings are also passed on into Cells (so kwargs.get, not kwargs.pop)
# border settings are also passed on into EvCells (so kwargs.get, not kwargs.pop)
self.header_line_char = hchar[0] if hchar else self.header_line_char
self.border_width = kwargs.get("border_width", self.border_width)
self.corner_char = kwargs.get("corner_char", self.corner_char)
self.header_line_char = kwargs.get("header_line_char", self.header_line_char)
self.corner_top_left = _to_ansi(kwargs.pop("corner_top_left", self.corner_char))
self.corner_top_right = _to_ansi(kwargs.pop("corner_top_right", self.corner_char))
self.corner_bottom_left = _to_ansi(kwargs.pop("corner_bottom_left", self.corner_char))
self.corner_bottom_right = _to_ansi(kwargs.pop("corner_bottom_right", self.corner_char))
self.corner_top_left_char = _to_ansi(kwargs.pop("corner_top_left_char", self.corner_char))
self.corner_top_right_char = _to_ansi(kwargs.pop("corner_top_right_char", self.corner_char))
self.corner_bottom_left_char = _to_ansi(kwargs.pop("corner_bottom_left_char", self.corner_char))
self.corner_bottom_right_char = _to_ansi(kwargs.pop("corner_bottom_right_char", self.corner_char))
self.options.update(kwargs)
self._balance()
def reformat_column(self, index, **kwargs):
"""
Sends custom options to a specific column in the table. The column
is identified by its index in the table (0-Ncol)
"""
if index > len(self.table):
raise Exception("Not a valid column index")
self.table[index].reformat(force_width=True, **kwargs)
self._balance()
def get(self):
"""
Return lines of table as a list
@ -1156,9 +1295,12 @@ def _test():
table = EvTable("{yHeading1{n", "{gHeading2{n", table=[[1,2,3],[4,5,6],[7,8,9]], border="cells")
table.add_column("{rThis is long data{n", "{bThis is even longer data{n")
table.add_row("This is a single row")
col = EvColumn("Test1", "Test3", "Test4", width=10)
table.add_column(col)
print unicode(table)
table.reformat(width=50)
print unicode(table)
return table