Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / python / text.py
1 # -*- test-case-name: twisted.test.test_text -*-
2 #
3 # Copyright (c) Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6
7 """
8 Miscellany of text-munging functions.
9 """
10
11 import string
12 import types
13
14
15 def stringyString(object, indentation=''):
16     """
17     Expansive string formatting for sequence types.
18
19     list.__str__ and dict.__str__ use repr() to display their
20     elements.  This function also turns these sequence types
21     into strings, but uses str() on their elements instead.
22
23     Sequence elements are also displayed on seperate lines,
24     and nested sequences have nested indentation.
25     """
26     braces = ''
27     sl = []
28
29     if type(object) is types.DictType:
30         braces = '{}'
31         for key, value in object.items():
32             value = stringyString(value, indentation + '   ')
33             if isMultiline(value):
34                 if endsInNewline(value):
35                     value = value[:-len('\n')]
36                 sl.append("%s %s:\n%s" % (indentation, key, value))
37             else:
38                 # Oops.  Will have to move that indentation.
39                 sl.append("%s %s: %s" % (indentation, key,
40                                          value[len(indentation) + 3:]))
41
42     elif type(object) in (types.TupleType, types.ListType):
43         if type(object) is types.TupleType:
44             braces = '()'
45         else:
46             braces = '[]'
47
48         for element in object:
49             element = stringyString(element, indentation + ' ')
50             sl.append(string.rstrip(element) + ',')
51     else:
52         sl[:] = map(lambda s, i=indentation: i+s,
53                     string.split(str(object),'\n'))
54
55     if not sl:
56         sl.append(indentation)
57
58     if braces:
59         sl[0] = indentation + braces[0] + sl[0][len(indentation) + 1:]
60         sl[-1] = sl[-1] + braces[-1]
61
62     s = string.join(sl, "\n")
63
64     if isMultiline(s) and not endsInNewline(s):
65         s = s + '\n'
66
67     return s
68
69 def isMultiline(s):
70     """Returns True if this string has a newline in it."""
71     return (string.find(s, '\n') != -1)
72
73 def endsInNewline(s):
74     """Returns True if this string ends in a newline."""
75     return (s[-len('\n'):] == '\n')
76
77
78 def greedyWrap(inString, width=80):
79     """Given a string and a column width, return a list of lines.
80
81     Caveat: I'm use a stupid greedy word-wrapping
82     algorythm.  I won't put two spaces at the end
83     of a sentence.  I don't do full justification.
84     And no, I've never even *heard* of hypenation.
85     """
86
87     outLines = []
88
89     #eww, evil hacks to allow paragraphs delimited by two \ns :(
90     if inString.find('\n\n') >= 0:
91         paragraphs = string.split(inString, '\n\n')
92         for para in paragraphs:
93             outLines.extend(greedyWrap(para, width) + [''])
94         return outLines
95     inWords = string.split(inString)
96
97     column = 0
98     ptr_line = 0
99     while inWords:
100         column = column + len(inWords[ptr_line])
101         ptr_line = ptr_line + 1
102
103         if (column > width):
104             if ptr_line == 1:
105                 # This single word is too long, it will be the whole line.
106                 pass
107             else:
108                 # We've gone too far, stop the line one word back.
109                 ptr_line = ptr_line - 1
110             (l, inWords) = (inWords[0:ptr_line], inWords[ptr_line:])
111             outLines.append(string.join(l,' '))
112
113             ptr_line = 0
114             column = 0
115         elif not (len(inWords) > ptr_line):
116             # Clean up the last bit.
117             outLines.append(string.join(inWords, ' '))
118             del inWords[:]
119         else:
120             # Space
121             column = column + 1
122     # next word
123
124     return outLines
125
126
127 wordWrap = greedyWrap
128
129 def removeLeadingBlanks(lines):
130     ret = []
131     for line in lines:
132         if ret or line.strip():
133             ret.append(line)
134     return ret
135
136 def removeLeadingTrailingBlanks(s):
137     lines = removeLeadingBlanks(s.split('\n'))
138     lines.reverse()
139     lines = removeLeadingBlanks(lines)
140     lines.reverse()
141     return '\n'.join(lines)+'\n'
142
143 def splitQuoted(s):
144     """Like string.split, but don't break substrings inside quotes.
145
146     >>> splitQuoted('the \"hairy monkey\" likes pie')
147     ['the', 'hairy monkey', 'likes', 'pie']
148
149     Another one of those \"someone must have a better solution for
150     this\" things.  This implementation is a VERY DUMB hack done too
151     quickly.
152     """
153     out = []
154     quot = None
155     phrase = None
156     for word in s.split():
157         if phrase is None:
158             if word and (word[0] in ("\"", "'")):
159                 quot = word[0]
160                 word = word[1:]
161                 phrase = []
162
163         if phrase is None:
164             out.append(word)
165         else:
166             if word and (word[-1] == quot):
167                 word = word[:-1]
168                 phrase.append(word)
169                 out.append(" ".join(phrase))
170                 phrase = None
171             else:
172                 phrase.append(word)
173
174     return out
175
176 def strFile(p, f, caseSensitive=True):
177     """Find whether string p occurs in a read()able object f
178     @rtype: C{bool}
179     """
180     buf = ""
181     buf_len = max(len(p), 2**2**2**2)
182     if not caseSensitive:
183         p = p.lower()
184     while 1:
185         r = f.read(buf_len-len(p))
186         if not caseSensitive:
187             r = r.lower()
188         bytes_read = len(r)
189         if bytes_read == 0:
190             return False
191         l = len(buf)+bytes_read-buf_len
192         if l <= 0:
193             buf = buf + r
194         else:
195             buf = buf[l:] + r
196         if buf.find(p) != -1:
197             return True
198