srcanamdw/codescanner/pyinstaller/optik/textwrap.py
author noe\swadi
Thu, 18 Feb 2010 12:29:02 +0530
changeset 1 22878952f6e2
permissions -rw-r--r--
Committing the CodeScanner Core tool This component has been moved from the StaticAnaApps package. BUG : 5889 (http://developer.symbian.org/webbugs/show_bug.cgi?id=5889).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     1
"""Text wrapping and filling.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     2
"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     3
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     4
# Copyright (C) 1999-2001 Gregory P. Ward.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     5
# Copyright (C) 2002, 2003 Python Software Foundation.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     6
# Written by Greg Ward <gward@python.net>
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     7
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     8
__revision__ = "$Id: textwrap.py,v 1.1 2009/02/05 23:03:30 stechong Exp $"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     9
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    10
import string, re
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    11
import types
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    12
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    13
# Do the right thing with boolean values for all known Python versions
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    14
# (so this module can be copied to projects that don't depend on Python
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    15
# 2.3, e.g. Optik and Docutils).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    16
try:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    17
    True, False
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    18
except NameError:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    19
    (True, False) = (1, 0)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    20
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    21
# For Python 1.5, just ignore unicode (try it as str)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    22
try:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    23
    unicode
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    24
except NameError:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    25
    unicode=str
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    26
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    27
__all__ = ['TextWrapper', 'wrap', 'fill']
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    28
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    29
# Hardcode the recognized whitespace characters to the US-ASCII
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    30
# whitespace characters.  The main reason for doing this is that in
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    31
# ISO-8859-1, 0xa0 is non-breaking whitespace, so in certain locales
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    32
# that character winds up in string.whitespace.  Respecting
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    33
# string.whitespace in those cases would 1) make textwrap treat 0xa0 the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    34
# same as any other whitespace char, which is clearly wrong (it's a
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    35
# *non-breaking* space), 2) possibly cause problems with Unicode,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    36
# since 0xa0 is not in range(128).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    37
_whitespace = '\t\n\x0b\x0c\r '
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    38
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    39
class TextWrapper:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    40
    """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    41
    Object for wrapping/filling text.  The public interface consists of
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    42
    the wrap() and fill() methods; the other methods are just there for
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    43
    subclasses to override in order to tweak the default behaviour.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    44
    If you want to completely replace the main wrapping algorithm,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    45
    you'll probably have to override _wrap_chunks().
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    46
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    47
    Several instance attributes control various aspects of wrapping:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    48
      width (default: 70)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    49
        the maximum width of wrapped lines (unless break_long_words
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    50
        is false)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    51
      initial_indent (default: "")
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    52
        string that will be prepended to the first line of wrapped
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    53
        output.  Counts towards the line's width.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    54
      subsequent_indent (default: "")
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    55
        string that will be prepended to all lines save the first
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    56
        of wrapped output; also counts towards each line's width.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    57
      expand_tabs (default: true)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    58
        Expand tabs in input text to spaces before further processing.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    59
        Each tab will become 1 .. 8 spaces, depending on its position in
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    60
        its line.  If false, each tab is treated as a single character.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    61
      replace_whitespace (default: true)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    62
        Replace all whitespace characters in the input text by spaces
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    63
        after tab expansion.  Note that if expand_tabs is false and
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    64
        replace_whitespace is true, every tab will be converted to a
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    65
        single space!
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    66
      fix_sentence_endings (default: false)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    67
        Ensure that sentence-ending punctuation is always followed
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    68
        by two spaces.  Off by default because the algorithm is
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    69
        (unavoidably) imperfect.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    70
      break_long_words (default: true)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    71
        Break words longer than 'width'.  If false, those words will not
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    72
        be broken, and some lines might be longer than 'width'.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    73
    """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    74
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    75
    whitespace_trans = string.maketrans(_whitespace, ' ' * len(_whitespace))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    76
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    77
    unicode_whitespace_trans = {}
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    78
    uspace = ord(unicode(' '))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    79
    for x in map(ord, _whitespace):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    80
        unicode_whitespace_trans[x] = uspace
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    81
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    82
    # This funky little regex is just the trick for splitting
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    83
    # text up into word-wrappable chunks.  E.g.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    84
    #   "Hello there -- you goof-ball, use the -b option!"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    85
    # splits into
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    86
    #   Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option!
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    87
    # (after stripping out empty strings).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    88
    try:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    89
        wordsep_re = re.compile(r'(\s+|'                  # any whitespace
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    90
                                r'[^\s\w]*\w{2,}-(?=\w{2,})|' # hyphenated words
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    91
                                r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))')   # em-dash
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    92
    except:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    93
        # Under python 1.5, the above regular expression does not compile because
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    94
        # of positive look-behind assertions (?<=). This stripped down version
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    95
        # does but it causes some regressions in the testsuite. Better than
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    96
        # nothing...
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    97
        wordsep_re = re.compile(r'(\s+|'                  # any whitespace
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    98
                                r'[^\s\w]*\w{2,}-(?=\w{2,})|' # hyphenated words
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    99
                                r')')   # em-dash
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   100
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   101
    # XXX this is not locale- or charset-aware -- string.lowercase
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   102
    # is US-ASCII only (and therefore English-only)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   103
    sentence_end_re = re.compile(r'[%s]'              # lowercase letter
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   104
                                 r'[\.\!\?]'          # sentence-ending punct.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   105
                                 r'[\"\']?'           # optional end-of-quote
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   106
                                 % string.lowercase)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   107
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   108
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   109
    def __init__(self,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   110
                 width=70,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   111
                 initial_indent="",
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   112
                 subsequent_indent="",
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   113
                 expand_tabs=True,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   114
                 replace_whitespace=True,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   115
                 fix_sentence_endings=False,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   116
                 break_long_words=True):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   117
        self.width = width
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   118
        self.initial_indent = initial_indent
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   119
        self.subsequent_indent = subsequent_indent
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   120
        self.expand_tabs = expand_tabs
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   121
        self.replace_whitespace = replace_whitespace
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   122
        self.fix_sentence_endings = fix_sentence_endings
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   123
        self.break_long_words = break_long_words
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   124
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   125
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   126
    # -- Private methods -----------------------------------------------
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   127
    # (possibly useful for subclasses to override)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   128
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   129
    def _munge_whitespace(self, text):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   130
        """_munge_whitespace(text : string) -> string
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   131
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   132
        Munge whitespace in text: expand tabs and convert all other
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   133
        whitespace characters to spaces.  Eg. " foo\tbar\n\nbaz"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   134
        becomes " foo    bar  baz".
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   135
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   136
        if self.expand_tabs:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   137
            text = string.expandtabs(text)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   138
        if self.replace_whitespace:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   139
            if isinstance(text, types.StringType):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   140
                text = string.translate(text, self.whitespace_trans)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   141
            elif isinstance(text, types.UnicodeType):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   142
                # This has to be Python 2.0+ (no unicode before), so
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   143
                # use directly string methods (the string module does not
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   144
                # support translate() with dictionary for unicode).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   145
                text = text.translate(self.unicode_whitespace_trans)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   146
        return text
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   147
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   148
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   149
    def _split(self, text):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   150
        """_split(text : string) -> [string]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   151
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   152
        Split the text to wrap into indivisible chunks.  Chunks are
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   153
        not quite the same as words; see wrap_chunks() for full
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   154
        details.  As an example, the text
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   155
          Look, goof-ball -- use the -b option!
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   156
        breaks into the following chunks:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   157
          'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   158
          'use', ' ', 'the', ' ', '-b', ' ', 'option!'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   159
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   160
        chunks = self.wordsep_re.split(text)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   161
        chunks = filter(None, chunks)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   162
        return chunks
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   163
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   164
    def _fix_sentence_endings(self, chunks):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   165
        """_fix_sentence_endings(chunks : [string])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   166
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   167
        Correct for sentence endings buried in 'chunks'.  Eg. when the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   168
        original text contains "... foo.\nBar ...", munge_whitespace()
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   169
        and split() will convert that to [..., "foo.", " ", "Bar", ...]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   170
        which has one too few spaces; this method simply changes the one
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   171
        space to two.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   172
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   173
        i = 0
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   174
        pat = self.sentence_end_re
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   175
        while i < len(chunks)-1:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   176
            if chunks[i+1] == " " and pat.search(chunks[i]):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   177
                chunks[i+1] = "  "
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   178
                i = i+2
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   179
            else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   180
                i = i+1
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   181
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   182
    def _handle_long_word(self, chunks, cur_line, cur_len, width):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   183
        """_handle_long_word(chunks : [string],
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   184
                             cur_line : [string],
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   185
                             cur_len : int, width : int)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   186
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   187
        Handle a chunk of text (most likely a word, not whitespace) that
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   188
        is too long to fit in any line.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   189
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   190
        space_left = max(width - cur_len, 1)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   191
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   192
        # If we're allowed to break long words, then do so: put as much
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   193
        # of the next chunk onto the current line as will fit.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   194
        if self.break_long_words:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   195
            cur_line.append(chunks[0][0:space_left])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   196
            chunks[0] = chunks[0][space_left:]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   197
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   198
        # Otherwise, we have to preserve the long word intact.  Only add
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   199
        # it to the current line if there's nothing already there --
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   200
        # that minimizes how much we violate the width constraint.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   201
        elif not cur_line:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   202
            cur_line.append(chunks.pop(0))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   203
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   204
        # If we're not allowed to break long words, and there's already
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   205
        # text on the current line, do nothing.  Next time through the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   206
        # main loop of _wrap_chunks(), we'll wind up here again, but
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   207
        # cur_len will be zero, so the next line will be entirely
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   208
        # devoted to the long word that we can't handle right now.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   209
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   210
    def _wrap_chunks(self, chunks):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   211
        """_wrap_chunks(chunks : [string]) -> [string]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   212
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   213
        Wrap a sequence of text chunks and return a list of lines of
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   214
        length 'self.width' or less.  (If 'break_long_words' is false,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   215
        some lines may be longer than this.)  Chunks correspond roughly
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   216
        to words and the whitespace between them: each chunk is
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   217
        indivisible (modulo 'break_long_words'), but a line break can
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   218
        come between any two chunks.  Chunks should not have internal
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   219
        whitespace; ie. a chunk is either all whitespace or a "word".
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   220
        Whitespace chunks will be removed from the beginning and end of
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   221
        lines, but apart from that whitespace is preserved.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   222
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   223
        lines = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   224
        if self.width <= 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   225
            raise ValueError("invalid width %r (must be > 0)" % self.width)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   226
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   227
        while chunks:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   228
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   229
            # Start the list of chunks that will make up the current line.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   230
            # cur_len is just the length of all the chunks in cur_line.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   231
            cur_line = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   232
            cur_len = 0
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   233
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   234
            # Figure out which static string will prefix this line.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   235
            if lines:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   236
                indent = self.subsequent_indent
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   237
            else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   238
                indent = self.initial_indent
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   239
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   240
            # Maximum width for this line.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   241
            width = self.width - len(indent)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   242
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   243
            # First chunk on line is whitespace -- drop it, unless this
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   244
            # is the very beginning of the text (ie. no lines started yet).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   245
            if string.strip(chunks[0]) == '' and lines:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   246
                del chunks[0]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   247
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   248
            while chunks:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   249
                l = len(chunks[0])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   250
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   251
                # Can at least squeeze this chunk onto the current line.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   252
                if cur_len + l <= width:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   253
                    cur_line.append(chunks.pop(0))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   254
                    cur_len = cur_len + l
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   255
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   256
                # Nope, this line is full.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   257
                else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   258
                    break
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   259
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   260
            # The current line is full, and the next chunk is too big to
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   261
            # fit on *any* line (not just this one).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   262
            if chunks and len(chunks[0]) > width:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   263
                self._handle_long_word(chunks, cur_line, cur_len, width)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   264
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   265
            # If the last chunk on this line is all whitespace, drop it.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   266
            if cur_line and string.strip(cur_line[-1]) == '':
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   267
                del cur_line[-1]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   268
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   269
            # Convert current line back to a string and store it in list
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   270
            # of all lines (return value).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   271
            if cur_line:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   272
                lines.append(indent + string.join(cur_line, ''))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   273
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   274
        return lines
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   275
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   276
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   277
    # -- Public interface ----------------------------------------------
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   278
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   279
    def wrap(self, text):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   280
        """wrap(text : string) -> [string]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   281
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   282
        Reformat the single paragraph in 'text' so it fits in lines of
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   283
        no more than 'self.width' columns, and return a list of wrapped
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   284
        lines.  Tabs in 'text' are expanded with string.expandtabs(),
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   285
        and all other whitespace characters (including newline) are
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   286
        converted to space.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   287
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   288
        text = self._munge_whitespace(text)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   289
        indent = self.initial_indent
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   290
        chunks = self._split(text)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   291
        if self.fix_sentence_endings:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   292
            self._fix_sentence_endings(chunks)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   293
        return self._wrap_chunks(chunks)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   294
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   295
    def fill(self, text):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   296
        """fill(text : string) -> string
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   297
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   298
        Reformat the single paragraph in 'text' to fit in lines of no
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   299
        more than 'self.width' columns, and return a new string
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   300
        containing the entire wrapped paragraph.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   301
        """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   302
        return string.join(self.wrap(text), "\n")
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   303
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   304
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   305
# -- Convenience interface ---------------------------------------------
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   306
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   307
def wrap(text, width=70, **kwargs):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   308
    """Wrap a single paragraph of text, returning a list of wrapped lines.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   309
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   310
    Reformat the single paragraph in 'text' so it fits in lines of no
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   311
    more than 'width' columns, and return a list of wrapped lines.  By
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   312
    default, tabs in 'text' are expanded with string.expandtabs(), and
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   313
    all other whitespace characters (including newline) are converted to
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   314
    space.  See TextWrapper class for available keyword args to customize
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   315
    wrapping behaviour.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   316
    """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   317
    kwargs["width"] = width
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   318
    w = apply(TextWrapper, (), kwargs)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   319
    return w.wrap(text)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   320
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   321
def fill(text, width=70, **kwargs):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   322
    """Fill a single paragraph of text, returning a new string.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   323
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   324
    Reformat the single paragraph in 'text' to fit in lines of no more
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   325
    than 'width' columns, and return a new string containing the entire
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   326
    wrapped paragraph.  As with wrap(), tabs are expanded and other
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   327
    whitespace characters converted to space.  See TextWrapper class for
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   328
    available keyword args to customize wrapping behaviour.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   329
    """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   330
    kwargs["width"] = width
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   331
    w = apply(TextWrapper, (), kwargs)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   332
    return w.fill(text)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   333
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   334
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   335
# -- Loosely related functionality -------------------------------------
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   336
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   337
def dedent(text):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   338
    """dedent(text : string) -> string
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   339
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   340
    Remove any whitespace than can be uniformly removed from the left
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   341
    of every line in `text`.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   342
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   343
    This can be used e.g. to make triple-quoted strings line up with
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   344
    the left edge of screen/whatever, while still presenting it in the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   345
    source code in indented form.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   346
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   347
    For example:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   348
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   349
        def test():
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   350
            # end first line with \ to avoid the empty line!
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   351
            s = '''\
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   352
            hello
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   353
              world
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   354
            '''
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   355
            print repr(s)          # prints '    hello\n      world\n    '
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   356
            print repr(dedent(s))  # prints 'hello\n  world\n'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   357
    """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   358
    lines = string.split(string.expandtabs(text), '\n')
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   359
    margin = None
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   360
    for line in lines:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   361
        content = string.lstrip(line)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   362
        if not content:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   363
            continue
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   364
        indent = len(line) - len(content)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   365
        if margin is None:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   366
            margin = indent
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   367
        else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   368
            margin = min(margin, indent)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   369
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   370
    if margin is not None and margin > 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   371
        for i in range(len(lines)):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   372
            lines[i] = lines[i][margin:]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   373
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   374
    return string.join(lines, "\n")