views:

41

answers:

2

I am trying to use textwrap to format an import file that is quite particular in how it is formatted. Basically, it is as follows (line length shortened for simplicity):

abcdef <- Ok line
abcdef 
 ghijk <- Note leading space to indicate wrapped line
 lm

Now, I have got code to work as follows:

wrapper = TextWrapper(width=80, subsequent_indent=' ', break_long_words=True, break_on_hyphens=False)
for l in lines:
  wrapline=wrapper.wrap(l)

This works nearly perfectly, however, the text wrapping code doesn't do a hard break at the 80 character mark, it tries to be smart and break on a space (at approx 20 chars in).

I have got round this by replacing all spaces in the string list with a unique character (#), wrapping them and then removing the character, but surely there must be a cleaner way?

N.B Any possible answers need to work on Python 2.4 - sorry!

+1  A: 

It sounds like you are disabling most of the functionality of TextWrapper, and then trying to add a little of your own. I think you'd be better off writing your own function or class. If I understand you right, you're simply looking for lines longer than 80 chars, and breaking them at the 80-char mark, and indenting the remainder by one space.

For example, this:

s = """\
This line is fine.
This line is very long and should wrap, It'll end up on a few lines.
A short line.
"""

def hard_wrap(s, n, indent):
    wrapped = ""
    n_next = n - len(indent)
    for l in s.split('\n'):
        first, rest = l[:n], l[n:]
        wrapped += first + "\n"
        while rest:
            next, rest = rest[:n_next], rest[n_next:]
            wrapped += indent + next + "\n"
    return wrapped

print hard_wrap(s, 20, " ")

produces:

This line is fine.
This line is very lo
 ng and should wrap,
  It'll end up on a
 few lines.
A short line.
Ned Batchelder
A: 

A generator-based version might be a better solution for you, since it wouldn't need to load the entire string in memory at once:

def hard_wrap(input, width, indent=' '):
   for line in input:
      indent_width = width - len(indent)
      yield line[:width]
      line = line[width:]
      while line:
         yield '\n' + indent + line[:indent_width]
         line = line[indent_width:]

Use it like this:

from StringIO import StringIO # Makes strings look like files

s = """abcdefg
abcdefghijklmnopqrstuvwxyz"""

for line in hard_wrap(StringIO(s), 12):
   print line,

Which prints:

abcdefg
abcdefghijkl 
 mnopqrstuvw 
 xyz
Triptych