mirror of
https://github.com/kastdeur/dotfiles.git
synced 2024-11-18 01:13:31 +01:00
225 lines
6.7 KiB
Python
225 lines
6.7 KiB
Python
|
#!/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 <chris.arndt@web.de
|
||
|
"""
|
||
|
i = []
|
||
|
while 1:
|
||
|
# line not long enough already?
|
||
|
if len(' '.join(line)) < width:
|
||
|
if not i:
|
||
|
# index list is exhausted
|
||
|
# get list if indices excluding last word
|
||
|
i = range(max(1, len(line)-1))
|
||
|
# and shuffle it
|
||
|
random.shuffle(i)
|
||
|
# append space to a random word and remove its index
|
||
|
line[i.pop(0)] += ' '
|
||
|
else:
|
||
|
# line has reached specified width or wider
|
||
|
return ' '.join(line)
|
||
|
|
||
|
|
||
|
# }}}
|
||
|
# FillParagraphs(text, width=80, justify=0): {{{
|
||
|
def FillParagraphs(text, width=80, justify=0):
|
||
|
"""Split a text into paragraphs and wrap them to width linelength.
|
||
|
|
||
|
Optionally justify the paragraphs (i.e. stretch lines to fill width).
|
||
|
|
||
|
Inter-word space is reduced to one space character and paragraphs are
|
||
|
always separated by two newlines. Indention is currently also lost.
|
||
|
|
||
|
Author: Christopher Arndt <chris.arndt@web.de
|
||
|
"""
|
||
|
# split taxt into paragraphs at occurences of two or more newlines
|
||
|
paragraphs = re.split(r'\n\n+', text)
|
||
|
for i in range(len(paragraphs)):
|
||
|
# split paragraphs into a list of words
|
||
|
words = paragraphs[i].strip().split()
|
||
|
line = []; new_par = []
|
||
|
while 1:
|
||
|
if words:
|
||
|
if len(' '.join(line + [words[0]])) > 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
|