#!/usr/bin/env python """Contains functions to do word-wrapping on text paragraphs.""" import string import re, random import operator # JustifyLine(line, width): {{{ def JustifyLine(line, width): """Stretch a line to width by filling in spaces at word gaps. The gaps are picked randomly one-after-another, before it starts over again. Author: Christopher Arndt width and line: # the line is already long enough -> add it to paragraph if justify: # stretch line to fill width new_par.append(JustifyLine(line, width)) else: new_par.append(' '.join(line)) line = [] else: # append next word line.append(words.pop(0)) else: # last line in paragraph new_par.append(' '.join(line)) line = [] break # replace paragraph with formatted version paragraphs[i] = '\n'.join(new_par) # return paragraphs separated by two newlines return '\n\n'.join(paragraphs) # }}} # IndentParagraphs(text, width=80, indent=0, justify=0): {{{ def IndentParagraphs(text, width=80, indent=0, justify=0): """Indent a paragraph, i.e: . left (and optionally right) justify text to given width . add an extra indent if desired. This is nothing but a wrapper around FillParagraphs """ retText = re.sub(r"^|\n", "\g<0>" + " "*indent, \ FillParagraphs(text, width, justify)) retText = re.sub(r"\n+$", '', retText) return retText # }}} # OffsetText(text, indent): {{{ def OffsetText(text, indent): return re.sub("^|\n", "\g<0>" + " "*indent, text) # }}} # RightJustify(lines, width): {{{ def RightJustify(lines, width): if width == 0: width = TextWidth(lines) text = "" for line in lines.split("\n"): text += " "*(width - len(line)) + line + "\n" text = re.sub('\n$', '', text) return text # }}} # CenterText(lines, width): {{{ def CenterText(lines, width): text = '' for line in lines.split("\n"): text += " "*(width/2 - len(line)/2) + line + '\n' return text # }}} # TextWidth(text): {{{ def TextWidth(text): """ TextWidth(text) returns the 'width' of the text, i.e the length of the longest segment in the text not containing new-lines. """ return max(map(len, text.split('\n'))) # }}} # FormatTable(tableText, ROW_SPACE=2, COL_SPACE = 3, \ {{{ # COL_WIDTH=30, TABLE_WIDTH=80, justify=0): def FormatTable(tableText, ROW_SPACE=2, COL_SPACE = 3, \ COL_WIDTH=1000, justify=0, widths=None): """ FormatTable(tableText [, ROW_SPACE=2, COL_SPACE = 3, COL_WIDTH=30, justify=0]) returns string Given a 2 dimensional array of text as input, produces a plain text formatted string which resembles the table output. The optional arguments specify the inter row/column spacing and the column width. """ # first find out the max width of the columns # maxwidths is a dictionary, but can be accessed exactly like an # array because the keys are integers. if widths is None: widths = {} for row in tableText: cellwidths = map(TextWidth, row) for i in range(len(cellwidths)): # Using: dictionary.get(key, default) widths[i] = max(cellwidths[i], widths.get(i, -1)) # Truncate each of the maximum lengths to the maximum allowed. for i in range(0, len(widths)): widths[i] = min(widths[i], COL_WIDTH) if justify: formattedTable = [] for row in tableText: formattedTable.append(map(FillParagraphs, row, \ [COL_WIDTH]*len(row))) else: formattedTable = tableText retTableText = "" for row in formattedTable: rowtext = row[0] width = widths[0] for i in range(1, len(row)): rowtext = VertCatString(rowtext, width, " "*COL_SPACE) rowtext = VertCatString(rowtext, width + COL_SPACE, row[i]) width = width + COL_SPACE + widths[i] retTableText += string.join(rowtext, "") retTableText += "\n"*ROW_SPACE return re.sub(r"\n+$", "", retTableText) # }}} # VertCatString(string1, width1, string2): {{{ def VertCatString(string1, width1, string2): """ VertCatString(string1, width1=None, string2) returns string Concatenates string1 and string2 vertically. The lines are assumed to be "\n" seperated. width1 is the width of the string1 column (It is calculated if left out). (Width refers to the maximum length of each line of a string) NOTE: if width1 is specified < actual width, then bad things happen. """ lines1 = string1.split("\n") lines2 = string2.split("\n") if width1 is None: width1 = -1 for line in lines1: width1 = max(width1, len(line)) retlines = [] for i in range(0, max(len(lines1), len(lines2))): if i >= len(lines1): lines1.append(" "*width1) lines1[i] = lines1[i] + " "*(width1 - len(lines1[i])) if i >= len(lines2): lines2.append("") retlines.append(lines1[i] + lines2[i]) return string.join(retlines, "\n") # }}} # vim:et:sts=4:fdm=marker