1 {- 2 Mailing List Generator 3 ---------------------- 4 5 Written by Paul Hudak, January 1992. 6 7 8 This program takes an ascii file of the form: 9 10 Name1 11 Address1 12 City1 13 14 Name2 15 Address2 16 City2 17 18 ... 19 20 Namen 21 Addressn 22 Cityn 23 24 where each entry is up to 4 lines each and with at least one blank 25 line between entries, and writes a new file containing reformatted 26 entries along with LaTex commands, that, when run through Latex, will 27 generate a printout of the form: 28 29 Name1 Name2 Name3 30 Address1 Address2 Address3 31 City1 City2 City3 32 ... 33 34 which is suitably spaced to line up with the labels on a standard 35 8 1/2 X 11, 30-per-page mailing label sheet. 36 37 The program prompts the user for the name of the input file, and uses 38 that name with a ".tex" suffix for the name of the output file. That 39 output file may be LaTexed directly, but it expects the following .sty 40 file, whose name should be "labels.sty": 41 42 \documentstyle[11pt]{article} 43 \textheight=10.5in 44 \textwidth=9.0in 45 \topmargin=-1in 46 \oddsidemargin=-1in 47 \evensidemargin=-1in 48 \pagestyle{empty} 49 50 \newcommand{\leftspace}{.5in} 51 \newcommand{\horspace}{0in} 52 \newcommand{\vertspace}{.23in} 53 54 \newcommand{\lpage}[3] 55 {\newpage 56 \vspace*{.05in} 57 \noindent 58 #1#2#3} 59 60 \newcommand{\sblock}[3] 61 {\lline{#1}{#2}{#3}\\} 62 63 \newcommand{\lblock}[9] 64 {\lline{#1}{#2}{#3}\vspace{\vertspace}\\ 65 \lline{#4}{#5}{#6}\vspace{\vertspace}\\ 66 \lline{#7}{#8}{#9}\vspace{\vertspace}\\} 67 68 \newcommand{\lline}[3] 69 {\hspace*{\leftspace} 70 \lab{#1}\hspace{\horspace} 71 \lab{#2}\hspace{\horspace} 72 \lab{#3}} 73 74 \newcommand{\lab}[1] 75 {\begin{tabular}{p{2.5in}} 76 #1 77 \end{tabular}} 78 79 80 Desired enhancements: 81 --------------------- 82 allow more than one input file for same output file 83 do character conversion for LaTex to avoid having to put "\&", etc. on input 84 85 -} 86 87 88 module Main where 89 90 type Line = String 91 type Entry = [Line] 92 type FileName = String 93 type UserInput = [FileName] 94 95 maxLineLength = 35 :: Int 96 97 main = do 98 putStr "\n\nWelcome to the LaTex Mailing List Generator.\n\ 99 \(Please type Cntrl-D at file prompt to exit.)\n" 100 s <- getContents 101 mainLoop (lines s) 102 103 mainLoop :: UserInput -> IO () 104 mainLoop fns = 105 putStr "\nFile to be converted: " >> 106 case fns of 107 [] -> putStr "\nGoodbye!\n" 108 (fn:fns') -> catch (readFile fn >>= process (fn ++ ".tex") fns') 109 (\err -> putStr ("\nCan't read " ++fn++ "; try again.\n") >> 110 mainLoop fns') 111 112 113 process :: FileName -> UserInput -> String -> IO () 114 process out fns rawText = 115 writeFile out "% Latex Mailing List.\n\n\ 116 \\\input{labels.sty}\n\n\ 117 \\\begin{document}\n\n" >> 118 loop (paras (lines rawText)) 119 where loop [] = appendFile out "\n\\end{document}\n" >> 120 putStr ("\nConversion completed; file " ++out++ " written.\n") >> 121 mainLoop fns 122 loop ps = writePage out ps loop 123 124 paras :: [Line] -> [Entry] 125 paras [] = [] 126 paras lns = p : paras (dropWhile blankLine lns') 127 where (p,lns') = break blankLine lns 128 blankLine = all (\c -> c==' ' || c=='\t') 129 130 writePage :: FileName -> [Entry] -> ([Entry]-> IO ()) -> IO () 131 writePage out ps cont = 132 appendFile out "\\lpage\n" >> 133 writeBlock out ps long 9 >>= \ ps -> 134 writeBlock out ps long 9 >>= \ ps -> 135 writeBlock out ps long 9 >>= \ ps -> 136 writeBlock out ps short 3 >>= 137 cont 138 139 -- got to here (partain) 140 141 long = "{\\lblock{\n" 142 short = "{\\sblock{\n" 143 144 writeBlock :: FileName -> [Entry] -> String -> Int -> IO [Entry] 145 writeBlock out ps kind size = 146 appendFile out kind >> 147 loop ps 1 148 where loop (e:es) n = 149 writeEntry out e >> 150 (if n==size then appendFile out "\n}}\n" >> 151 return es 152 else appendFile out "\n}{\n" >> 153 loop es (n+1) ) 154 loop [] n = loop (take (size-n+1) (repeat [])) n 155 156 writeEntry :: FileName -> Entry -> IO () 157 writeEntry out entry = loop entry 1 where 158 loop [] n = 159 if n<5 then loop (take (5-n) (repeat "")) n 160 else return () 161 loop (ln:lns) n = 162 if n>4 163 then putStr 164 "\nThis entry was truncated to 4 lines:\n" >> 165 print entry >> 166 putStr "\n" >> 167 return () 168 else appendFile out ln >> 169 appendFile out "\\\\ " >> 170 (if length ln>maxLineLength 171 then putStr "\nThis line may be too long:\n" >> 172 putStr ln >> 173 putStr "\nCheck LaTex output to be sure.\n" >> 174 loop lns (n+1) 175 else loop lns (n+1) )