{-
Mailing List Generator
----------------------
Written by Paul Hudak, January 1992.
This program takes an ascii file of the form:
Name1
Address1
City1
Name2
Address2
City2
...
Namen
Addressn
Cityn
where each entry is up to 4 lines each and with at least one blank
line between entries, and writes a new file containing reformatted
entries along with LaTex commands, that, when run through Latex, will
generate a printout of the form:
Name1 Name2 Name3
Address1 Address2 Address3
City1 City2 City3
...
which is suitably spaced to line up with the labels on a standard
8 1/2 X 11, 30-per-page mailing label sheet.
The program prompts the user for the name of the input file, and uses
that name with a ".tex" suffix for the name of the output file. That
output file may be LaTexed directly, but it expects the following .sty
file, whose name should be "labels.sty":
\documentstyle[11pt]{article}
\textheight=10.5in
\textwidth=9.0in
\topmargin=-1in
\oddsidemargin=-1in
\evensidemargin=-1in
\pagestyle{empty}
\newcommand{\leftspace}{.5in}
\newcommand{\horspace}{0in}
\newcommand{\vertspace}{.23in}
\newcommand{\lpage}[3]
{\newpage
\vspace*{.05in}
\noindent
#1#2#3}
\newcommand{\sblock}[3]
{\lline{#1}{#2}{#3}\\}
\newcommand{\lblock}[9]
{\lline{#1}{#2}{#3}\vspace{\vertspace}\\
\lline{#4}{#5}{#6}\vspace{\vertspace}\\
\lline{#7}{#8}{#9}\vspace{\vertspace}\\}
\newcommand{\lline}[3]
{\hspace*{\leftspace}
\lab{#1}\hspace{\horspace}
\lab{#2}\hspace{\horspace}
\lab{#3}}
\newcommand{\lab}[1]
{\begin{tabular}{p{2.5in}}
#1
\end{tabular}}
Desired enhancements:
---------------------
allow more than one input file for same output file
do character conversion for LaTex to avoid having to put "\&", etc. on input
-}
module Main where
type Line = String
type Entry = [Line]
type FileName = String
type UserInput = [FileName]
maxLineLength = 35 :: Int
main = do
putStr "\n\nWelcome to the LaTex Mailing List Generator.\n\
\(Please type Cntrl-D at file prompt to exit.)\n"
s <- getContents
mainLoop (lines s)
mainLoop :: UserInput -> IO ()
mainLoop fns =
putStr "\nFile to be converted: " >>
case fns of
[] -> putStr "\nGoodbye!\n"
(fn:fns') -> catch (readFile fn >>= process (fn ++ ".tex") fns')
(\err -> putStr ("\nCan't read "++fn++
" - try again.\n"++show err) >>
mainLoop fns')
process :: FileName -> UserInput -> String -> IO ()
process out fns rawText =
writeFile out "% Latex Mailing List.\n\n\
\\\input{labels.sty}\n\n\
\\\begin{document}\n\n" >>
loop (paras (lines rawText))
where loop [] = appendFile out "\n\\end{document}\n" >>
putStr ("\nConversion completed; file " ++out++ " written.\n") >>
mainLoop fns
loop ps = writePage out ps loop
paras :: [Line] -> [Entry]
paras [] = []
paras lns = p : paras (dropWhile blankLine lns')
where (p,lns') = break blankLine lns
blankLine = all (\c -> c==' ' || c=='\t')
writePage :: FileName -> [Entry] -> ([Entry]-> IO ()) -> IO ()
writePage out ps cont =
appendFile out "\\lpage\n" >>
writeBlock out ps long 9 >>= \ ps ->
writeBlock out ps long 9 >>= \ ps ->
writeBlock out ps long 9 >>= \ ps ->
writeBlock out ps short 3 >>=
cont
-- got to here (partain)
long = "{\\lblock{\n"
short = "{\\sblock{\n"
writeBlock :: FileName -> [Entry] -> String -> Int -> IO [Entry]
writeBlock out ps kind size =
appendFile out kind >>
loop ps 1
where loop (e:es) n =
writeEntry out e >>
(if n==size then appendFile out "\n}}\n" >>
return es
else appendFile out "\n}{\n" >>
loop es (n+1) )
loop [] n = loop (take (size-n+1) (repeat [])) n
writeEntry :: FileName -> Entry -> IO ()
writeEntry out entry = loop entry 1 where
loop [] n =
if n<5 then loop (take (5-n) (repeat "")) n
else return ()
loop (ln:lns) n =
if n>4
then putStr
"\nThis entry was truncated to 4 lines:\n" >>
print entry >>
putStr "\n" >>
return ()
else appendFile out ln >>
appendFile out "\\\\ " >>
(if length ln>maxLineLength
then putStr "\nThis line may be too long:\n" >>
putStr ln >>
putStr "\nCheck LaTex output to be sure.\n" >>
loop lns (n+1)
else loop lns (n+1) )