Saltycrane logo

SaltyCrane Blog

Notes on Python, Django, and web development on Ubuntu Linux

    

Python word wrap function

I'm working on creating function headers for our C development code. These headers include the function name, a purpose statement, input/output lists, etc. So my solution (because I'm lazy and prefer scripting to writing hundreds of lines of not-actually-code) is to write a Python script to write the headers. I put all the pertinent information (function names, variable names, descriptions, etc.) in an Excel spreadsheet and I'm using Python to read the data and properly format it. (See here and here for more info on using Python w/ Excel.) Things are going pretty well. The spreadsheet (and the script) are getting a little messy, but overall, it is faster (I think), more fun (definitely) and I believe will produce more consistent results. It also allows me to be more flexible if names or descriptions change in the future because I only need to change the information once in the spreadsheet instead of mutiple places in the actual .c files.

One of the rules for the function headers is that they must be 80 columns or less in width. It is annoying to wrap everything by hand so I wrote a Python function to do the wrapping. (I know Emacs could probably do all this in about 2 lines of Lisp, but I haven't learned that much yet.) Here is the script with a couple of examples:

def word_wrap(string, width=80, ind1=0, ind2=0, prefix=''):
    """ word wrapping function.
        string: the string to wrap
        width: the column number to wrap at
        prefix: prefix each line with this string (goes before any indentation)
        ind1: number of characters to indent the first line
        ind2: number of characters to indent the rest of the lines
    """
    string = prefix + ind1 * " " + string
    newstring = ""
    while len(string) > width:
        # find position of nearest whitespace char to the left of "width"
        marker = width - 1
        while not string[marker].isspace():
            marker = marker - 1

        # remove line from original string and add it to the new string
        newline = string[0:marker] + "\n"
        newstring = newstring + newline
        string = prefix + ind2 * " " + string[marker + 1:]

    return newstring + string
Example 1: wrap at 60 characters
string = "PURPOSE: To end world hunger, create peace for all people, solve all technological and scientific problems, make an exorbitant amount of money, and remain humble in the process."
print word_wrap(string, 60)
Results:
PURPOSE: To end world hunger, create peace for all people,
solve all technological and scientific problems, make an
exorbitant amount of money, and remain humble in the
process.
Example 2: wrap at 60 chars, with a prefix, and a hanging indent
print word_wrap(string, 60, 0, 9, " * ")
Results:
 * PURPOSE: To end world hunger, create peace for all
 *          people, solve all technological and scientific
 *          problems, make an exorbitant amount of money,
 *          and remain humble in the process.

Update 2008-09-18: I just found out there is a textwrap module in the Python Standard Library. See the docs at: http://docs.python.org/lib/module-textwrap.html.

7 Comments — feed icon Comments feed for this post


#1 Harshad commented on 2008-08-30:

Thank you for the code! I've used it in a small program I created - pietweet, a twitter client for python /commandline.

http://harshadsharma.com/doku.php/software:pietweet

Cheers!


#2 Eliot commented on 2008-09-18:

Harshad,
I'm glad it was useful for you. Pietweet looks like a cool program.


#3 Seun Osewa commented on 2009-01-04:

The python tetwrap module doesn't allow multiple paragraphs.


#4 Ed commented on 2009-11-19:

You mention emacs, but not knowing how to do it. The feature you want is built into emacs. Mark the buffer and then hit Alt-q (or M-q for the purists)


#5 Eliot commented on 2009-11-19:

Ed, thanks for the Emacs tip. I would do good to remember that keybinding!


#6 Arthur Dent commented on 2010-05-29:

It's an old post, but...

Get rid of the 'if'.

while len(string) > width: is enough.

In other words...

12 s/if/while/
13 d
14,22 s/^\t//
23,26 d

#7 Eliot commented on 2010-05-29:

Arthur Dent: That makes the code much cleaner! I don't know what I was thinking. I made the change above. Thanks for the tip.

Post a comment

Required
Required, but not displayed
Optional

Format using Markdown. (No HTML.)
  • Code blocks: prefix each line by at least 4 spaces or 1 tab (and a blank line before and after)
  • Code span: surround with backticks
  • Blockquotes: prefix lines to be quoted with >
  • Links: <URL>
  • Links w/ description: [description](URL)
Created with Django | Hosted by Slicehost