1
# -*- test-case-name: twisted.test.test_text -*-
3
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4
# See LICENSE for details.
7
"""Miscellany of text-munging functions.
12
def stringyString(object, indentation=''):
13
"""Expansive string formatting for sequence types.
15
list.__str__ and dict.__str__ use repr() to display their
16
elements. This function also turns these sequence types
17
into strings, but uses str() on their elements instead.
19
Sequence elements are also displayed on seperate lines,
20
and nested sequences have nested indentation.
25
if type(object) is types.DictType:
27
for key, value in object.items():
28
value = stringyString(value, indentation + ' ')
29
if isMultiline(value):
30
if endsInNewline(value):
31
value = value[:-len('\n')]
32
sl.append("%s %s:\n%s" % (indentation, key, value))
34
# Oops. Will have to move that indentation.
35
sl.append("%s %s: %s" % (indentation, key,
36
value[len(indentation) + 3:]))
38
elif type(object) in (types.TupleType, types.ListType):
39
if type(object) is types.TupleType:
44
for element in object:
45
element = stringyString(element, indentation + ' ')
46
sl.append(string.rstrip(element) + ',')
48
sl[:] = map(lambda s, i=indentation: i+s,
49
string.split(str(object),'\n'))
52
sl.append(indentation)
55
sl[0] = indentation + braces[0] + sl[0][len(indentation) + 1:]
56
sl[-1] = sl[-1] + braces[-1]
58
s = string.join(sl, "\n")
60
if isMultiline(s) and not endsInNewline(s):
66
"""Returns True if this string has a newline in it."""
67
return (string.find(s, '\n') != -1)
70
"""Returns True if this string ends in a newline."""
71
return (s[-len('\n'):] == '\n')
73
def docstringLStrip(docstring):
74
"""Gets rid of unsightly lefthand docstring whitespace residue.
76
You'd think someone would have done this already, but apparently
79
BUT since we're all using Python 2.1 now, use L{inspect.getdoc}
80
instead. I{This function should go away soon.}
86
docstring = string.replace(docstring, '\t', ' ' * 8)
87
lines = string.split(docstring,'\n')
90
for l in xrange(1,len(lines)):
92
if string.strip(line):
94
if line[leading] == ' ':
101
outlines = lines[0:1]
102
for l in xrange(1,len(lines)):
103
outlines.append(lines[l][leading:])
105
return string.join(outlines, '\n')
107
def greedyWrap(inString, width=80):
108
"""Given a string and a column width, return a list of lines.
110
Caveat: I'm use a stupid greedy word-wrapping
111
algorythm. I won't put two spaces at the end
112
of a sentence. I don't do full justification.
113
And no, I've never even *heard* of hypenation.
118
#eww, evil hacks to allow paragraphs delimited by two \ns :(
119
if inString.find('\n\n') >= 0:
120
paragraphs = string.split(inString, '\n\n')
121
for para in paragraphs:
122
outLines.extend(greedyWrap(para) + [''])
124
inWords = string.split(inString)
129
column = column + len(inWords[ptr_line])
130
ptr_line = ptr_line + 1
134
# This single word is too long, it will be the whole line.
137
# We've gone too far, stop the line one word back.
138
ptr_line = ptr_line - 1
139
(l, inWords) = (inWords[0:ptr_line], inWords[ptr_line:])
140
outLines.append(string.join(l,' '))
144
elif not (len(inWords) > ptr_line):
145
# Clean up the last bit.
146
outLines.append(string.join(inWords, ' '))
156
wordWrap = greedyWrap
158
def removeLeadingBlanks(lines):
161
if ret or line.strip():
165
def removeLeadingTrailingBlanks(s):
166
lines = removeLeadingBlanks(s.split('\n'))
168
lines = removeLeadingBlanks(lines)
170
return '\n'.join(lines)+'\n'
173
"""Like string.split, but don't break substrings inside quotes.
175
>>> splitQuoted('the \"hairy monkey\" likes pie')
176
['the', 'hairy monkey', 'likes', 'pie']
178
Another one of those \"someone must have a better solution for
179
this\" things. This implementation is a VERY DUMB hack done too
185
for word in s.split():
187
if word and (word[0] in ("\"", "'")):
195
if word and (word[-1] == quot):
198
out.append(" ".join(phrase))
205
def strFile(p, f, caseSensitive=True):
206
"""Find whether string p occurs in a read()able object f
210
buf_len = max(len(p), 2**2**2**2)
211
if not caseSensitive:
214
r = f.read(buf_len-len(p))
215
if not caseSensitive:
220
l = len(buf)+bytes_read-buf_len
225
if buf.find(p) != -1: