Import Oort Gnus v0.19.
[elisp/gnus.git-] / texi / texi2latex.el
1 ;;; texi2latex.el --- convert a texi file into a LaTeX file.
2 ;; Copyright (C) 1996 Lars Magne Ingebrigtsen
3
4 (require 'cl)
5
6 (defun latexi-discard-until (string)
7   (let ((beg (match-beginning 0)))
8     (unless (re-search-forward (concat "^@end +" string "[ \t]*\n") nil t)
9       (error "No end: %s" string))
10     (delete-region beg (match-end 0))))
11
12 (defun latexi-strip-line ()
13   (delete-region (progn (beginning-of-line) (point))
14                  (progn (forward-line 1) (point))))
15
16 (defun latexi-switch-line (command arg)
17   (latexi-strip-line)
18   (insert (format "\\%s{%s}\n" command arg)))
19
20 (defun latexi-index-command (command arg)
21   (latexi-strip-line)
22   (insert (format "\\gnus%sindex{%s}\n" 
23                   (if (equal command "kindex") "k" "")
24                   arg)))
25
26 (defun latexi-begin-command (command)
27   (latexi-strip-line)
28   (insert (format "\\begin{%s}\n" command)))
29
30 (defun latexi-exchange-command (command arg)
31   (delete-region (match-beginning 0) (match-end 0))
32   (insert (format "\\%s{%s}" command arg)))
33
34 (defun latexi-translate ()
35   "Translate."
36   (interactive)
37   (latexi-translate-file "gnus")
38   (latexi-translate-file "gnus-faq")
39   (latexi-translate-file "message" t)
40   (latexi-translate-file "emacs-mime" t)
41   (latexi-translate-file "sieve" t)
42   (latexi-translate-file "pgg" t))
43
44 (defun latexi-translate-file (file &optional as-a-chapter)
45   "Translate file a LaTeX file."
46   (let ((item-string "")
47         (item-stack nil)
48         (list-stack nil)
49         (latexi-buffer (get-buffer-create "*LaTeXi*"))
50         verbatim
51         (regexp 
52          (concat 
53             "@\\([^{} \t\n]+\\)"
54             "\\(\\( +\\(.*$\\)\\|[ \t]*$\\)\\|{\\([^}]*\\)}\\)"))
55         (cur (find-file-noselect (concat (or (getenv "srcdir") ".") 
56                                          "/" file ".texi")))
57         (times 3)
58         (chapter 0)
59         command arg)
60     (pop-to-buffer latexi-buffer)
61     (buffer-disable-undo)
62     (erase-buffer)
63     (insert-buffer-substring cur)
64     (goto-char (point-min))
65     (latexi-strip-line)
66     (latexi-translate-string "%@{" "\\gnuspercent{}\\gnusbraceleft{}")
67     (latexi-translate-string "%@}" "\\gnuspercent{}\\gnusbraceright{}")
68     (latexi-translate-string "%1@{" "\\gnuspercent{}1\\gnusbraceright{}")
69     (latexi-translate-string "@*" "\\newline{}")
70     (latexi-translate-string "S@{" "S\\gnusbraceleft{}")
71     (latexi-translate-string "@code{\\222}" "@code{\\gnusbackslash{}222}")
72     (latexi-translate-string "@code{\\264}" "@code{\\gnusbackslash{}264}")
73     (latexi-translate-string "@samp{\\Deleted}" "@samp{\\gnusbackslash{}Deleted}")
74     (latexi-translate-string "@samp{\\Seen}" "@samp{\\gnusbackslash{}Seen}")
75     (latexi-translate-string "@file{c:\\myhome}" "@file{c:\\gnusbackslash{}myhome}")
76 ;    (while (re-search-forward "{\"[^\"]*\\(\\\\\\)[^\"]*\"}\\\\" nil t)
77 ;      (replace-match "\\verb+\\\\+ " t t))
78     (while (not (zerop (decf times)))
79       (goto-char (point-min))
80       (while (re-search-forward regexp nil t)
81         (setq command (match-string 1))
82         (if (match-beginning 3)
83             (progn
84               (setq arg (or (match-string 4) ""))
85               (save-match-data
86                 (when (string-match "[ \t]+$" arg)
87                   (setq arg (substring arg 0 (match-beginning 0)))))
88               (cond 
89                ((member command '("c" "comment"))
90                 (if (string-match "@icon" (or arg ""))
91                     (progn
92                       (beginning-of-line)
93                       (delete-region (point) (+ (point) 4))
94                       (insert "\\gnus"))
95                   (delete-region (match-beginning 0) 
96                                  (progn (end-of-line) (point))))
97                 (if (equal arg "@head")
98                     (insert "\\gnusinteresting")))
99                ((member command '("setfilename" "set"
100                                   "synindex" "setchapternewpage"
101                                   "summarycontents" "bye"
102                                   "top" "iftex" "cartouche" 
103                                   "iflatex" "finalout" "vskip"
104                                   "dircategory"))
105                 (latexi-strip-line))
106                ((member command '("menu" "tex" "ifinfo" "ignore" 
107                                   "ifnottex" "direntry"))
108                 (latexi-discard-until command))
109                ((member command '("subsection" "subsubsection"))
110                 (if as-a-chapter
111                     (latexi-switch-line (format "sub%s" command) arg)
112                   (latexi-switch-line command arg)))
113                ((member command '("heading"))
114                 (if as-a-chapter
115                     (latexi-switch-line "subsection*" arg)
116                   (latexi-switch-line "section*" arg)))
117                ((member command '("subheading"))
118                 (if as-a-chapter
119                     (latexi-switch-line "subsubsection*" arg)
120                   (latexi-switch-line "subsection*" arg)))
121                ((member command '("chapter"))
122                 (if (string-match "Index" arg)
123                     (latexi-strip-line)
124                   (if as-a-chapter
125                       (latexi-switch-line "gnussection" arg)
126                     (latexi-switch-line 
127                      (format 
128                       "gnus%s{%s}" command
129                       (format "\\epsfig{figure=ps/new-herd-%d,scale=.5}"
130                               (if (> (incf chapter) 9) 9 chapter)))
131                      arg))))
132                ((member command '("section"))
133                 (if as-a-chapter
134                     (latexi-switch-line "subsection" arg)
135                   (latexi-switch-line (format "gnus%s" command) arg)))
136                ((member command '("cindex" "findex" "kindex" "vindex"))
137                 (latexi-index-command command arg))
138                ((member command '("*"))
139                 (delete-char -2)
140                 (insert "\\\\"))
141                ((equal command "sp")
142                 (replace-match "" t t))
143                ((member command '("deffn" "defvar" "defun"))
144                 (replace-match "" t t))
145                ((equal command "node")
146                 (latexi-strip-line)
147                 (unless (string-match "Index" arg)
148                   (insert (format "\\label{%s}\n" arg))))
149                ((equal command "contents")
150                 (latexi-strip-line)
151                 ;;(insert (format "\\tableofcontents\n" arg))
152                 )
153                ((member command '("titlepage"))
154                 (latexi-begin-command command))
155                ((member command '("lisp" "example"))
156                 (latexi-strip-line)
157                 (insert (format "\\begin{verbatim}\n"))
158                 (setq verbatim (point)))
159                ((member command '("center"))
160                 (latexi-strip-line)
161                 (insert (format "\\begin{%s}%s\\end{%s}\n"
162                                 command arg command)))
163                ((member command '("end"))
164                 (cond
165                  ((member arg '("titlepage"))
166                   (latexi-strip-line)
167                   (insert (format "\\end{%s}\n" arg)))
168                  ((equal arg "quotation")
169                   (latexi-strip-line)
170                   (insert (format "\\end{verse}\n")))
171                  ((member arg '("lisp" "example"))
172                   (latexi-strip-line)
173                   (save-excursion
174                     (save-restriction
175                       (narrow-to-region verbatim (point))
176                       (goto-char (point-min))
177                       (while (search-forward "@{" nil t)
178                         (replace-match "{" t t))
179                       (goto-char (point-min))
180                       (while (search-forward "@}" nil t)
181                         (replace-match "}" t t))))
182                   (setq verbatim nil)
183                   (insert "\\end{verbatim}\n"))
184                  ((member arg '("table"))
185                   (setq item-string (pop item-stack))
186                   (latexi-strip-line)
187                   (insert (format "\\end{%slist}\n" (pop list-stack))))
188                  ((member arg '("itemize" "enumerate"))
189                   (setq item-string (pop item-stack))
190                   (latexi-strip-line)
191                   (insert (format "\\end{%s}\n" arg)))
192                  ((member arg '("iflatex" "iftex" "cartouche"))
193                   (latexi-strip-line))
194                  ((member arg '("deffn" "defvar" "defun"))
195                   (latexi-strip-line))
196                  (t
197                   (error "Unknown end arg: %s" arg))))
198                ((member command '("table"))
199                 (push item-string item-stack)
200                 (push (substring arg 1) list-stack)
201                 (setq item-string 
202                       (format "[@%s{%%s}]" (car list-stack)))
203                 (latexi-strip-line)
204                 (insert (format "\\begin{%slist}\n" (car list-stack))))
205                ((member command '("itemize" "enumerate"))
206                 (push item-string item-stack)
207                 (cond 
208                  ((member arg '("@bullet"))
209                   (setq item-string "[\\gnusbullet]"))
210                  (t
211                   (setq item-string "")))
212                 (latexi-strip-line)
213                 (insert (format "\\begin{%s}\n" command)))
214                ((member command '("item"))
215                 (latexi-strip-line)
216                 (insert (format "\\%s%s\n" command (format item-string arg))))
217                ((equal command "itemx")
218                 (latexi-strip-line)
219                 (insert (format "\\gnusitemx{%s}\n" (format item-string arg))))
220                ((eq (aref command 0) ?@)
221                 (goto-char (match-beginning 0))
222                 (delete-char 2)
223                 (insert "duppat{}"))
224                ((equal command "settitle")
225                 (latexi-strip-line)
226                 (if (not as-a-chapter)
227                     (insert 
228                      (format "\\newcommand{\\gnustitlename}{%s}\n" arg))))
229                ((equal command "title")
230                 (latexi-strip-line)
231                 (insert (format "\\gnustitlename{%s}\n" arg)))
232                ((equal command "author")
233                 (latexi-strip-line)
234                 (insert (format "\\gnusauthor{%s}\n" arg)))
235                ((equal command "quotation")
236                 (latexi-begin-command "verse"))
237                ((equal command "page")
238                 (latexi-strip-line)
239                 (insert (format "\\newpage\n" arg)))
240                ((equal command "'s")
241                 (goto-char (match-beginning 0))
242                 (delete-char 1))
243                ((equal command "include")
244                 (latexi-strip-line)
245                 (string-match "\\.texi" arg)
246                 (insert (format "\\input{%s.latexi}\n" 
247                                 (substring arg 0 (match-beginning 0)))))
248                ((equal command "noindent")
249                 (latexi-strip-line)
250                 (insert "\\noindent\n"))
251                ((equal command "printindex")
252                 (latexi-strip-line)
253                 ;;(insert 
254                 ;; (format 
255                 ;;  "\\begin{theindex}\\input{gnus.%s}\\end{theindex}\n" arg))
256                 )
257                (t
258                 (error "Unknown command (file %s line %d): %s"
259                        file
260                        (save-excursion
261                          (widen)
262                          (1+ (count-lines (point-min) (progn
263                                                         (beginning-of-line)
264                                                         (point)))))
265                        command))))
266           ;; These are commands with {}.
267           (setq arg (match-string 5))
268           (cond 
269            ((member command '("anchor"))
270             (latexi-strip-line))
271            ((member command '("ref" "xref" "pxref"))
272             (latexi-exchange-command (concat "gnus" command) arg))
273            ((member command '("sc" "file" "dfn" "emph" "kbd" "key" "uref"
274                               "code" "samp" "var" "strong" "i"
275                               "result" "email" "env" "r"))
276             (goto-char (match-beginning 0))
277             (delete-char 1)
278             (insert "\\gnus"))
279            ((member command '("acronym"))
280             (latexi-exchange-command (concat "gnus" command) (downcase arg)))
281            ((member command '("copyright" "footnote" "TeX"))
282             (goto-char (match-beginning 0))
283             (delete-char 1)
284             (insert "\\"))
285            ((member command '("dots"))
286             (goto-char (match-beginning 0))
287             (delete-region (match-beginning 0) (match-end 0))
288             (insert "..."))
289            ((eq (aref command 0) ?@)
290             (goto-char (match-beginning 0))
291             (delete-char 2)
292             (insert "duppat{}"))
293            (t
294             (error "Unknown command (file %s line %d): %s"
295                    file
296                    (save-excursion
297                      (widen)
298                      (1+ (count-lines (point-min) (progn
299                                                     (beginning-of-line)
300                                                     (point)))))
301                    command))))))
302     (latexi-translate-string "$" "\\gnusdollar{}")
303     (latexi-translate-string "&" "\\gnusampersand{}")
304     (latexi-translate-string "%" "\\gnuspercent{}")
305     (latexi-translate-string "#" "\\gnushash{}")
306     (latexi-translate-string "^" "\\gnushat{}")
307     (latexi-translate-string "~" "\\gnustilde{}")
308     (latexi-translate-string "_" "\\gnusunderline{}")
309     (latexi-translate-string "¬" "\\gnusnot{}")
310     (goto-char (point-min))
311     (while (search-forward "duppat{}" nil t)
312       (replace-match "@" t t))
313     (latexi-translate-string "@@" "@")
314     (latexi-translate-string "<" "\\gnusless{}")
315     (latexi-translate-string ">" "\\gnusgreater{}")
316     (goto-char (point-min))
317     (search-forward "label{Top}" nil t)
318     (while (re-search-forward "\\\\[ntr]\\b" nil t)
319       (when (save-match-data
320               (or (not (save-excursion
321                          (search-backward "begin{verbatim}" nil t)))
322                   (> (save-excursion
323                        (search-backward "end{verbatim"))
324                      (save-excursion
325                        (search-backward "begin{verbatim}")))))
326         (goto-char (match-beginning 0))
327         (delete-char 1)
328         (insert "\\gnusbackslash{}")))
329     (latexi-translate-string "\\\\" "\\gnusbackslash{}")
330     (goto-char (point-min))
331     (while (re-search-forward "\\\\[][{}]" nil t)
332       (goto-char (match-beginning 0))
333       (delete-char 1))
334     (latexi-contributors)
335     (let ((coding-system-for-write 'iso-8859-1))
336       (write-region (point-min) (point-max) (concat file ".latexi")))))
337
338 (defun latexi-translate-string (in out)
339   (let (yes)
340     (goto-char (point-min))
341     (search-forward "label{Top}" nil t)
342     (while (search-forward in nil t)
343       (when (save-match-data
344               (or (not (save-excursion
345                          (search-backward "begin{verbatim}" nil t)))
346                   (> (save-excursion
347                        (re-search-backward "end{verbatim}\\|end{verse}"))
348                      (save-excursion
349                        (re-search-backward
350                         "begin{verbatim}\\|begin{verse}")))))
351         (replace-match out t t)))))
352
353 (defun latexi-contributors ()
354   (goto-char (point-min))
355   (when (re-search-forward "^Also thanks to the following" nil t)
356     (forward-line 2)
357     (narrow-to-region
358      (point)
359      (1- (search-forward "\n\n")))
360     (when (re-search-backward "^and" nil t)
361       (latexi-strip-line))
362     (goto-char (point-min))
363     (while (re-search-forward "[.,] *$" nil t)
364       (replace-match "" t t))
365     (goto-char (point-min))
366     (let (names)
367       (while (not (eobp))
368         (push (buffer-substring (point) (progn (end-of-line) (point)))
369               names)
370         (forward-line 1))
371       (delete-region (point-min) (point-max))
372       (insert "\\begin{tabular}{lll}\n")
373       (setq names (nreverse (delete "" names)))
374       (while names
375         (insert (pop names) " & " (or (pop names) "\\mbox{}") 
376                 " & " (or (pop names) "\\mbox{}") 
377                 "\\\\\n"))
378       (insert "\\end{tabular}\n")
379       (widen))))
380