Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

text.py 5.3KB

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