1
0
Fork 0
mirror of https://github.com/kastdeur/dotfiles.git synced 2024-11-18 01:13:31 +01:00
dotfiles/vim/vim-latex/doc/db2vim/textutils.py

225 lines
6.7 KiB
Python
Raw Permalink Normal View History

#!/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