aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/python/text.py
blob: 9887e70ea54448f0a10450b839522fa8cb39bea5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# -*- test-case-name: twisted.test.test_text -*-
#
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.

"""
Miscellany of text-munging functions.
"""


def stringyString(object, indentation=''):
    """
    Expansive string formatting for sequence types.

    C{list.__str__} and C{dict.__str__} use C{repr()} to display their
    elements.  This function also turns these sequence types
    into strings, but uses C{str()} on their elements instead.

    Sequence elements are also displayed on seperate lines, and nested
    sequences have nested indentation.
    """
    braces = ''
    sl = []

    if type(object) is dict:
        braces = '{}'
        for key, value in object.items():
            value = stringyString(value, indentation + '   ')
            if isMultiline(value):
                if endsInNewline(value):
                    value = value[:-len('\n')]
                sl.append("%s %s:\n%s" % (indentation, key, value))
            else:
                # Oops.  Will have to move that indentation.
                sl.append("%s %s: %s" % (indentation, key,
                                         value[len(indentation) + 3:]))

    elif type(object) is tuple or type(object) is list:
        if type(object) is tuple:
            braces = '()'
        else:
            braces = '[]'

        for element in object:
            element = stringyString(element, indentation + ' ')
            sl.append(element.rstrip() + ',')
    else:
        sl[:] = map(lambda s, i=indentation: i + s,
                   str(object).split('\n'))

    if not sl:
        sl.append(indentation)

    if braces:
        sl[0] = indentation + braces[0] + sl[0][len(indentation) + 1:]
        sl[-1] = sl[-1] + braces[-1]

    s = "\n".join(sl)

    if isMultiline(s) and not endsInNewline(s):
        s = s + '\n'

    return s


def isMultiline(s):
    """
    Returns C{True} if this string has a newline in it.
    """
    return (s.find('\n') != -1)


def endsInNewline(s):
    """
    Returns C{True} if this string ends in a newline.
    """
    return (s[-len('\n'):] == '\n')


def greedyWrap(inString, width=80):
    """
    Given a string and a column width, return a list of lines.

    Caveat: I'm use a stupid greedy word-wrapping
    algorythm.  I won't put two spaces at the end
    of a sentence.  I don't do full justification.
    And no, I've never even *heard* of hypenation.
    """

    outLines = []

    #eww, evil hacks to allow paragraphs delimited by two \ns :(
    if inString.find('\n\n') >= 0:
        paragraphs = inString.split('\n\n')
        for para in paragraphs:
            outLines.extend(greedyWrap(para, width) + [''])
        return outLines
    inWords = inString.split()

    column = 0
    ptr_line = 0
    while inWords:
        column = column + len(inWords[ptr_line])
        ptr_line = ptr_line + 1

        if (column > width):
            if ptr_line == 1:
                # This single word is too long, it will be the whole line.
                pass
            else:
                # We've gone too far, stop the line one word back.
                ptr_line = ptr_line - 1
            (l, inWords) = (inWords[0:ptr_line], inWords[ptr_line:])
            outLines.append(' '.join(l))

            ptr_line = 0
            column = 0
        elif not (len(inWords) > ptr_line):
            # Clean up the last bit.
            outLines.append(' '.join(inWords))
            del inWords[:]
        else:
            # Space
            column = column + 1
    # next word

    return outLines


wordWrap = greedyWrap


def removeLeadingBlanks(lines):
    ret = []
    for line in lines:
        if ret or line.strip():
            ret.append(line)
    return ret


def removeLeadingTrailingBlanks(s):
    lines = removeLeadingBlanks(s.split('\n'))
    lines.reverse()
    lines = removeLeadingBlanks(lines)
    lines.reverse()
    return '\n'.join(lines)+'\n'


def splitQuoted(s):
    """
    Like a string split, but don't break substrings inside quotes.

    >>> splitQuoted('the "hairy monkey" likes pie')
    ['the', 'hairy monkey', 'likes', 'pie']

    Another one of those "someone must have a better solution for
    this" things.  This implementation is a VERY DUMB hack done too
    quickly.
    """
    out = []
    quot = None
    phrase = None
    for word in s.split():
        if phrase is None:
            if word and (word[0] in ("\"", "'")):
                quot = word[0]
                word = word[1:]
                phrase = []

        if phrase is None:
            out.append(word)
        else:
            if word and (word[-1] == quot):
                word = word[:-1]
                phrase.append(word)
                out.append(" ".join(phrase))
                phrase = None
            else:
                phrase.append(word)

    return out


def strFile(p, f, caseSensitive=True):
    """
    Find whether string C{p} occurs in a read()able object C{f}.

    @rtype: C{bool}
    """
    buf = ""
    buf_len = max(len(p), 2**2**2**2)
    if not caseSensitive:
        p = p.lower()
    while 1:
        r = f.read(buf_len-len(p))
        if not caseSensitive:
            r = r.lower()
        bytes_read = len(r)
        if bytes_read == 0:
            return False
        l = len(buf)+bytes_read-buf_len
        if l <= 0:
            buf = buf + r
        else:
            buf = buf[l:] + r
        if buf.find(p) != -1:
            return True