add a wrap_string function that works properly

This commit is contained in:
Nick Lanham 2011-03-01 19:11:53 +01:00
parent ccc047848a
commit 426eea154e
1 changed files with 76 additions and 0 deletions

View File

@ -99,3 +99,79 @@ def format_column(col, lim):
def format_row(row,column_widths):
return "".join([format_column(row[i],column_widths[i]) for i in range(0,len(row))])
import re
from collections import deque
_strip_re = re.compile("\{!.*?!\}")
def wrap_string(string,width,min_lines=0,strip_colors=True):
"""
Wrap a string to fit in a particular width. Returns a list of output lines.
:param string: str, the string to wrap
:param width: int, the maximum width of a line of text
:param min_lines: int, extra lines will be added so the output tuple contains at least min_lines lines
:param strip_colors: boolean, if True, text in {!!} blocks will not be considered as adding to the
width of the line. They will still be present in the output.
"""
ret = []
s1 = string.split("\n")
def insert_clr(s,offset,mtchs,clrs):
end_pos = offset+len(s)
while mtchs and (mtchs[0] <= end_pos) and (mtchs[0] >= offset):
mtc = mtchs.popleft()-offset
clr = clrs.popleft()
end_pos += len(clr)
s = "%s%s%s"%(s[:mtc],clr,s[mtc:])
return s
for s in s1:
cur_pos = offset = 0
if strip_colors:
mtchs = deque()
clrs = deque()
for m in _strip_re.finditer(s):
mtchs.append(m.start())
clrs.append(m.group())
cstr = _strip_re.sub('',s)
else:
cstr = s
while len(cstr) > width:
sidx = cstr.rfind(" ",0,width-1)
sidx += 1
if sidx > 0:
if strip_colors:
to_app = cstr[0:sidx]
to_app = insert_clr(to_app,offset,mtchs,clrs)
ret.append(to_app)
offset += len(to_app)
else:
ret.append(cstr[0:sidx])
cstr = cstr[sidx:]
if not cstr:
cstr = None
break
else:
# can't find a reasonable split, just split at width
if strip_colors:
to_app = cstr[0:width]
to_app = insert_clr(to_app,offset,mtchs,clrs)
ret.append(to_app)
offset += len(to_app)
else:
ret.append(cstr[0:width])
cstr = cstr[width:]
if not cstr:
cstr = None
break
if cstr != None:
if strip_colors:
ret.append(insert_clr(cstr,offset,mtchs,clrs))
else:
ret.append(cstr)
if min_lines>0:
for i in range(len(ret),min_lines):
ret.append(" ")
return ret