[project @ 1996-07-25 21:02:03 by partain]
[nofib.git] / real / maillist / Main.hs
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)
109 (\err -> putStr ("\nCan't read " ++fn++ "; try again.\n") >>
110 mainLoop fns') >>= \ stuff ->
111 process (fn ++ ".tex") fns' stuff
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 -> ([Entry]->Dialogue) ->
145 Dialogue
146 writeBlock out ps kind size cont =
147 appendFile out kind exit $
148 loop ps 1
149 where loop (e:es) n =
150 writeEntry out e $
151 (if n==size then appendFile out "\n}}\n" exit $
152 cont es
153 else appendFile out "\n}{\n" exit $
154 loop es (n+1) )
155 loop [] n = loop (take (size-n+1) (repeat [])) n
156
157 writeEntry :: FileName -> Entry -> Dialogue -> Dialogue
158 writeEntry out entry cont = loop entry 1 where
159 loop [] n =
160 if n<5 then loop (take (5-n) (repeat "")) n
161 else cont
162 loop (ln:lns) n =
163 if n>4
164 then appendChan stdout
165 "\nThis entry was truncated to 4 lines:\n" exit $
166 appendChan stdout (show entry) exit $
167 appendChan stdout "\n" exit $
168 cont
169 else appendFile out ln exit $
170 appendFile out "\\\\ " exit $
171 (if length ln>maxLineLength
172 then appendChan stdout "\nThis line may be too long:\n" exit $
173 appendChan stdout ln exit $
174 appendChan stdout "\nCheck LaTex output to be sure.\n" exit$
175 loop lns (n+1)
176 else loop lns (n+1) )