*** empty log message ***
1 parent b62c1a5 commit 71fa72773042f40571103b064dfa4ea9138b36c6
@tundra tundra authored on 9 Oct 2002
Showing 1 changed file
View
354
mailfmt 0 → 100644
#!/usr/bin/env python
# mailfmt - Copyright (c) 2002, TundraWare Inc., All Rights Reserved
# Reformat mail/news to cleanup quotation characters and maintain
# reasonable line widths.
 
PROGNAME = "MAILFMT"
RCSID = "$Id: mailfmt,v 1.3 2002/10/09 19:34:16 tundra Exp $"
VERSION = RCSID.split()[2]
 
##########
# Imports
##########
 
import getopt
import os
import sys
 
 
##########
# Booleans
##########
 
FALSE = 0==1
TRUE = not FALSE
 
 
##########
# Identify The OS And Import OS-Specific Modules
##########
 
if os.name == 'nt':
WIN32 = TRUE
import win32clipboard
from win32ui import MessageBox
else:
WIN32 = FALSE
 
##########
# Constants & Tables
##########
 
# Constants
 
NOQUOTEMATCH = "!" + PROGNAME + "_NOMATCH!"
PMARK = "!" + PROGNAME + "_PARA!"
 
 
# Error Messages
 
eBADWIDTH = "Bogus Output Width!"
eNOCBDATA = "No Data In Clipboard!"
eNOTHING = "Nothing To Do!"
 
 
##########
# Function Defintions
##########
 
#####
# Display An Error
#####
 
def dsply_error(error="Unknown Error"):
if WIN32 and CLIPOUT:
MessageBox(error, PROGNAME + " " + VERSION)
else:
print PROGNAME + " " + VERSION +": " + error
 
# End of 'dsply_error()'
 
 
#####
# Get input from appropriate location
#####
 
def get_input():
 
if USECB:
win32clipboard.OpenClipboard()
try:
cb = win32clipboard.GetClipboardData()
except:
dsply_error(eNOCBDATA)
sys.exit(1)
win32clipboard.CloseClipboard()
else:
cb = sys.stdin.read()
 
return(cb)
 
# End of 'get_input()'
 
 
#####
# Split line into its quotation portion and its
# content portion, returning both in a list
#####
 
def line_quot(line):
content = line
while content[0] == ATTCHAR:
content = content[1:]
quotetxt = line.split(content)[0]
content = " ".join(content.split())
return([quotetxt, content])
 
 
 
# End of 'line_quot()'
 
 
#####
# Output the results
#####
 
def output(results):
 
# Add CRs for Win32 systems
if WIN32:
results= results.replace("\n", "\r\n")
 
if CLIPOUT:
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard() # Gotta do this to make writes globally visible
win32clipboard.SetClipboardText(results)
win32clipboard.CloseClipboard()
else:
print results
 
# End of 'output()'
 
 
#####
# Print Usage Information
#####
 
def usage():
print "mailfmt " + VERSION + " - Copyright 2002, TundraWare Inc., All Rights Reserved\n"
print "usage: mailfmt [-a] [-c char] [-h] [-i] [-o] [-r] [-v] [-w num] where,"
print " -a do not remove quotation characters"
print " -c char sets the quotation character to remove"
print " -h print this help information"
print " -i read input from stdin instead of clipboard"
print " (automatic on non-Win32 systems)"
print " -o print output instead of sending to clipboard"
print " (automatic on non-Win32 systems)"
print " -r do not wrap lines"
print " -v print detailed version information"
print " -w val sets output line width"
 
# End of 'usage()'
 
 
##########
# Program Entry Point
##########
 
# Program option defaults
 
ATTCHAR = '>'
CLIPOUT = TRUE
RMVQUOT = TRUE
USECB = TRUE
WIDTH = 75
WRAP = TRUE
 
 
# Command line processing
 
try:
opts, args = getopt.getopt(sys.argv[1:], '-ac:hiorvw:')
except getopt.GetoptError:
usage()
sys.exit(1)
 
for opt, val in opts:
if opt == "-a":
RMVQUOT = FALSE
if opt == "-c":
ATTCHAR = val
if opt == "-h":
usage()
sys.exit(0)
if opt == "-i":
USECB = FALSE
if opt == "-o":
CLIPOUT = FALSE
if opt == "-r":
WRAP = FALSE
if opt == "-v":
print RCSID
sys.exit(0)
if opt == "-w":
try: # Need this to catch silly user input for -w
WIDTH = int(val)
except:
dsply_error(eBADWIDTH)
sys.exit(1)
if WIDTH < 1:
dsply_error(eBADWIDTH)
sys.exit(1)
 
# Condition variables based on OS
 
if not WIN32:
USECB = FALSE
CLIPOUT = FALSE
 
# Make sure we have something to do
 
if (not RMVQUOT) and (not WRAP): # nothing to do
dsply_error(eNOTHING)
sys.exit(1)
 
 
# Get text to process
 
cb = get_input()
 
# Remove any nulls - these get embedded if the copy to
# the clipboard was done in a DOS command line box.
 
cb = cb.replace("\x00", "")
 
# Build work buffer - walk through the input
# splitting each line into a list - the first entry
# contains the quotation string, if any, the second
# the content of the line.
 
buffer = []
for line in cb.splitlines():
buffer.append(line_quot(line + " ")) # Trailing blank guarantees non-null
# string needed by line_quot()
 
# Mark the blank lines for special processing
 
for entry in buffer:
if entry[1] == "":
entry[1] = PMARK
 
 
# Remove leading quotation characters, unless told not to
 
if RMVQUOT:
for line in buffer:
line[0] = ""
 
 
# Wrap lines to specified width, unless told not to.
# This is tricky because there may or may not be leading quotation
# strings. If they are present, we want to preserve them in the
# wrapping process.
 
if WRAP:
 
# Walk through the current work buffer and concatenate
# adjacent lines with identical quotations
l=""
i = -1
lastquot = NOQUOTEMATCH # Make sure no match on first record
 
tmp = buffer
buffer=[]
lastquot = tmp[0][0]
content = tmp[0][1]
tmp = tmp[1:]
for entry in tmp:
if entry[1] == PMARK: # Blank lines output separately
buffer.append([lastquot, content]) # Output pending work
lastquot = entry[0] # Setup to output next time through
content = entry[1]
elif (entry[0] != lastquot) or (content == PMARK):
buffer.append([lastquot, content])
lastquot = entry[0]
content = entry[1]
else:
content += " " + entry[1] # make sure at least one space always
# separates concatenated lines
 
if content != "":
buffer.append([lastquot, content])
 
# Iterate across the results producing lines of appropriate length
# with correct quotation text, if any.
tmp = []
for entry in buffer:
# Figure out allowable width with quotation, if any
quot = entry[0]
width = WIDTH - len(quot)
 
if quot != "": # Adjust width if we will add pad later
width -= 1
 
# Format each output line to be WIDTH characters or less ending with
# a newline. The one exception happens if a single word is too
# long for the specified width. In this case, the quotation and word
# get output without regards to specified width.
 
s = ""
for word in entry[1].split():
 
if len(s + word) < width: # Normal case
s += (word + " ")
elif len(word) > width: # Single word too wide - output as is
if s != "": # Process any previous pending line
tmp.append([quot, s])
s = ""
tmp.append([quot, word])
elif len(s + word) == width: # Ends right on width boundary
tmp.append([quot, s + word])
s = ""
else: # New word makes line too long
tmp.append([quot, s])
s = word + " "
 
if s != "": # Process any last pending line
tmp.append([quot, s])
 
buffer = tmp
 
 
# Cleanup the final output buffer
 
for entry in buffer:
entry[1] = " ".join(entry[1].split()) # Delete trailing spaces
if entry[1] == PMARK: # Remove paragraph markers
entry[1] = ""
 
 
# Collapse the final work buffer into a single string.
# If there is an quotation string, place a space between
# it and the actual line contents
 
tmp = ""
for entry in buffer:
if entry[0] == "":
pad = ""
else:
pad = " "
tmp += entry[0] + pad + entry[1] + '\n'
 
 
# Send the output as user has specified
 
output(tmp)