wrapping email at 72 characters ?
Does anyone have a python snippet or something that helps format outgoing emails, so that lines wrap nicely at 72 characters? :) -- Geir Bækholt web-developer geirh@funcom.com funcom oslo | webdev-team
code that does the following whould do it: - read 72 characters into the email body - go backwards from there until you encounter an empty space - replace the empty space with a newline character - repeat the preceding steps, starting from the first character after the newline you just inserted. if there is already newlines in the body of text you can replace all of them with empty spaces before you start parsing. jens On Thursday, August 8, 2002, at 07:40 , Geir Bækholt wrote:
Does anyone have a python snippet or something that helps format outgoing emails, so that lines wrap nicely at 72 characters?
:)
-- Geir Bækholt web-developer geirh@funcom.com funcom oslo | webdev-team
On Thu, Aug 08, 2002 at 08:01:15AM -0400, Jens Vagelpohl wrote:
code that does the following whould do it:
- read 72 characters into the email body - go backwards from there until you encounter an empty space - replace the empty space with a newline character - repeat the preceding steps, starting from the first character after the newline you just inserted.
if there is already newlines in the body of text you can replace all of them with empty spaces before you start parsing.
but then you would lose double-newline paragraph boundaries. -- Paul Winkler "Welcome to Muppet Labs, where the future is made - today!"
so you add a check in there to see if it is a single or a multiple newline in one place and modify the behavior. no problem. jens On Thursday, August 8, 2002, at 05:21 , Paul Winkler wrote:
On Thu, Aug 08, 2002 at 08:01:15AM -0400, Jens Vagelpohl wrote:
code that does the following whould do it:
- read 72 characters into the email body - go backwards from there until you encounter an empty space - replace the empty space with a newline character - repeat the preceding steps, starting from the first character after the newline you just inserted.
if there is already newlines in the body of text you can replace all of them with empty spaces before you start parsing.
but then you would lose double-newline paragraph boundaries.
Here is a slightly more complicated set of functions that allow for wrapping text (it comes from BackTalk's TextBlockFormatter module): import string, math def format(text, max_width=80, indent=0, trailing_lines_indent_more=0): text = string.expandtabs(string.replace(text, '\r', '')) lines = string.split(text, '\n') aggregate = [] for line in lines: if len(line) <= max_width-1: # this line is short enough to output aggregate.append(line) else: lines = splitlongline(line, max_width) aggregate.extend(lines) out = [] i = 0 for line in aggregate: spaces = ' ' * indent if i != 0 and trailing_lines_indent_more: spaces = spaces + (' ' * trailing_lines_indent_more) out.append('%s%s' % (spaces, line)) i = i + 1 return string.join(out, '\n') def splitword(word, max_width=80, linepos=0): # some lines may have single words that exceed the max_width # We want to break apart long words into as many chunks as necessary if len(word) <= max_width: return [word] first_chunk_len = max_width-1-linepos firstchunk = word[:first_chunk_len] word = word[first_chunk_len:] numchunks = int(math.ceil(len(word) / float(max_width-1))) index = 0 tmp = [firstchunk] for chunknum in range(numchunks): chunk = word[index:index+max_width-1] tmp.append(chunk) index = index + max_width-1 return tmp def splitlongline(line, max_width=80): # split a "long" line defined by max_width into a list of lines line = string.strip(line) words = string.split(line, ' ') wordnum = 0 # iterate over all the words in the line, extending the word list # necessary for too-long words aggregate = [] linelen = 0 wordnum = 0 while words: word = words.pop(0) if not word: continue if len(word) > max_width: new_words = splitword(word, max_width, linelen) word = new_words[0] for new_word in new_words[1:]: words.insert(wordnum, new_word) wordnum = wordnum + 1 if words: next_word = words[0] else: next_word = None if next_word is None: aggregate.append(word) wordnum = wordnum + 1 continue maybe_len = linelen + len(word) + len(next_word) if maybe_len >= max_width-1: aggregate.append(word) aggregate.append(None) linelen = 0 else: aggregate.append(word) linelen = linelen + len(word) + 1 wordnum = wordnum + 1 s = "" last = None for item in aggregate: if item is None: s = '%s\n' % s elif last is None: s = '%s%s' % (s, item) else: s = '%s %s' % (s, item) last = item return string.split(s, '\n') long = """ To turn a component into a product you must fulfill many contracts. For the most part these contracts are not yet defined in terms of interfaces. Instead you must subclass from base classes that implement the contracts. This makes building products confusing, and this is an area that we are actively working on improving. Hereisalonglinethatshouldbecaughtandbrokenupbytheformatter,hopefullyitllgetsplitupwhenirunitthroughthere.""" long2 = """ Hereisalonglinethatshouldbecaughtandbrokenupbytheformatter,hopefullyitllgetsplitupwhenirunitthroughthere.""" long3 = """ To turn a component into a product you must fulfill many contracts. For the most part these contracts are not yet defined in terms of interfaces. Instead you must subclass from base classes that implement the contracts. This makes building products confusing, and this is an area that we are actively working on improving. Hereisalonglinethatshouldbecaughtandbrokenupbytheformatter,hopefullyitllgetsplitupwhenirunitthroughthere.""" if __name__ == '__main__': print format(long, 60, 10) print format(long) print format(long2, 60, 10) print format(long2) print format(long3, 60, 10) print format(long3) On Thu, 2002-08-08 at 21:53, Jens Vagelpohl wrote:
so you add a check in there to see if it is a single or a multiple newline in one place and modify the behavior. no problem.
jens
On Thursday, August 8, 2002, at 05:21 , Paul Winkler wrote:
On Thu, Aug 08, 2002 at 08:01:15AM -0400, Jens Vagelpohl wrote:
code that does the following whould do it:
- read 72 characters into the email body - go backwards from there until you encounter an empty space - replace the empty space with a newline character - repeat the preceding steps, starting from the first character after the newline you just inserted.
if there is already newlines in the body of text you can replace all of them with empty spaces before you start parsing.
but then you would lose double-newline paragraph boundaries.
_______________________________________________ Zope maillist - Zope@zope.org http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev )
Try this code from my MSWordMunger product (which predates Python 2.0 btw): from string import find, rfind, join def wordWrap(text, width): remaining = text wrapped = [] while len(remaining) > width: cut = width if remaining[cut] != ' ': cut = rfind(remaining, ' ', 0, cut-1) if cut == -1: cut = find(remaining, ' ', cut-1) if cut == -1: cut = len(remaining) wrapped.append(remaining[:cut]) remaining = remaining[cut+1:] if remaining: wrapped.append(remaining) return join(wrapped, '\n') hth, Casey On Thursday 08 August 2002 07:40 am, Geir Bækholt wrote:
Does anyone have a python snippet or something that helps format outgoing emails, so that lines wrap nicely at 72 characters?
:)
-- Geir Bækholt web-developer geirh@funcom.com funcom oslo | webdev-team
_______________________________________________ Zope maillist - Zope@zope.org http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev )
Hello Casey, Thursday, August 8, 2002, 2:43:57 PM, you wrote: CD> Try this code from my MSWordMunger product (which predates Python 2.0 btw): thanks .. with a few minor fixes it works perfectly for my needs. :-) Most notably : the following line doesn't make any sense: CD> if cut == -1: cut = find(remaining, ' ', cut-1) as cut-1 always will be -2 ... here is an updated version with support for existing newlines as well: from string import find, rfind, join def wordWrap(text, width): remaining = text wrapped = [] while len(remaining) > width: cut = width newline = find(remaining, '\n', 0, cut) if newline != -1: cut = newline elif remaining[cut] != ' ': temp = rfind(remaining, ' ', 0, cut-1) if temp == -1:temp = find(remaining, ' ', cut-1, len(remaining)) if temp == -1: temp = len(remaining) cut = temp wrapped.append(remaining[:cut]) remaining = remaining[cut+1:] if remaining: wrapped.append(remaining) return join(wrapped, '\n') thanks a lot , Casey :-) posted it to ZopeLabs : http://www.zopelabs.com/cookbook/1028832719 CD> On Thursday 08 August 2002 07:40 am, Geir Bækholt wrote:
Does anyone have a python snippet or something that helps format outgoing emails, so that lines wrap nicely at 72 characters?
-- Geir Bækholt web-developer geirh@funcom.com funcom oslo | webdev-team
participants (6)
-
Casey Duncan -
Chris McDonough -
Geir Bækholt -
Geir B�kholt -
Jens Vagelpohl -
Paul Winkler