Import Gnus v5.10.3.
[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" "group" "syncodeindex"))
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 '("subsubheading"))
122                 (if as-a-chapter
123                     (latexi-switch-line "subsubsubsection*" arg)
124                   (latexi-switch-line "subsubsection*" arg)))
125                ((member command '("chapter"))
126                 (if (string-match "Index" arg)
127                     (latexi-strip-line)
128                   (if as-a-chapter
129                       (latexi-switch-line "gnussection" arg)
130                     (latexi-switch-line 
131                      (format 
132                       "gnus%s{%s}" command
133                       (format "\\epsfig{figure=ps/new-herd-%d,scale=.5}"
134                               (if (> (incf chapter) 9) 9 chapter)))
135                      arg))))
136                ((member command '("section"))
137                 (if as-a-chapter
138                     (latexi-switch-line "subsection" arg)
139                   (latexi-switch-line (format "gnus%s" command) arg)))
140                ((member command '("cindex" "findex" "kindex" "vindex"))
141                 (latexi-index-command command arg))
142                ((member command '("*"))
143                 (delete-char -2)
144                 (insert "\\\\"))
145                ((equal command "sp")
146                 (replace-match "" t t))
147                ((equal command ":")
148                 (replace-match "" t t))
149                ((member command '("deffn" "defvar" "defun"))
150                 (replace-match "" t t))
151                ((equal command "node")
152                 (latexi-strip-line)
153                 (unless (string-match "Index" arg)
154                   (insert (format "\\label{%s}\n" arg))))
155                ((equal command "contents")
156                 (latexi-strip-line)
157                 ;;(insert (format "\\tableofcontents\n" arg))
158                 )
159                ((member command '("titlepage"))
160                 (latexi-begin-command command))
161                ((member command '("lisp" "example" "smallexample" "display"))
162                 (latexi-strip-line)
163                 (insert (format "\\begin{verbatim}\n"))
164                 (setq verbatim (point)))
165                ((member command '("center"))
166                 (latexi-strip-line)
167                 (insert (format "\\begin{%s}%s\\end{%s}\n"
168                                 command arg command)))
169                ((member command '("end"))
170                 (cond
171                  ((member arg '("titlepage"))
172                   (latexi-strip-line)
173                   (insert (format "\\end{%s}\n" arg)))
174                  ((equal arg "quotation")
175                   (latexi-strip-line)
176                   (insert (format "\\end{verse}\n")))
177                  ((member arg '("lisp" "example" "smallexample" "display"))
178                   (latexi-strip-line)
179                   (save-excursion
180                     (save-restriction
181                       (narrow-to-region verbatim (point))
182                       (goto-char (point-min))
183                       (while (search-forward "@{" nil t)
184                         (replace-match "{" t t))
185                       (goto-char (point-min))
186                       (while (search-forward "@}" nil t)
187                         (replace-match "}" t t))))
188                   (setq verbatim nil)
189                   (insert "\\end{verbatim}\n"))
190                  ((member arg '("table"))
191                   (setq item-string (pop item-stack))
192                   (latexi-strip-line)
193                   (insert (format "\\end{%slist}\n" (pop list-stack))))
194                  ((member arg '("itemize" "enumerate"))
195                   (setq item-string (pop item-stack))
196                   (latexi-strip-line)
197                   (insert (format "\\end{%s}\n" arg)))
198                  ((member arg '("iflatex" "iftex" "cartouche" "group"))
199                   (latexi-strip-line))
200                  ((member arg '("deffn" "defvar" "defun"))
201                   (latexi-strip-line))
202                  (t
203                   (error "Unknown end arg: %s" arg))))
204                ((member command '("table"))
205                 (push item-string item-stack)
206                 (push (substring arg 1) list-stack)
207                 (setq item-string 
208                       (format "[@%s{%%s}]" (car list-stack)))
209                 (latexi-strip-line)
210                 (insert (format "\\begin{%slist}\n" (car list-stack))))
211                ((member command '("itemize" "enumerate"))
212                 (push item-string item-stack)
213                 (cond 
214                  ((member arg '("@bullet"))
215                   (setq item-string "[\\gnusbullet]"))
216                  (t
217                   (setq item-string "")))
218                 (latexi-strip-line)
219                 (insert (format "\\begin{%s}\n" command)))
220                ((member command '("item"))
221                 (latexi-strip-line)
222                 (insert (format "\\%s%s\n" command (format item-string arg))))
223                ((equal command "itemx")
224                 (latexi-strip-line)
225                 (insert (format "\\gnusitemx{%s}\n" (format item-string arg))))
226                ((eq (aref command 0) ?@)
227                 (goto-char (match-beginning 0))
228                 (delete-char 2)
229                 (insert "duppat{}"))
230                ((equal command "settitle")
231                 (latexi-strip-line)
232                 (if (not as-a-chapter)
233                     (insert 
234                      (format "\\newcommand{\\gnustitlename}{%s}\n" arg))))
235                ((equal command "title")
236                 (latexi-strip-line)
237                 (insert (format "\\gnustitlename{%s}\n" arg)))
238                ((equal command "author")
239                 (latexi-strip-line)
240                 (insert (format "\\gnusauthor{%s}\n" arg)))
241                ((equal command "quotation")
242                 (latexi-begin-command "verse"))
243                ((equal command "page")
244                 (latexi-strip-line)
245                 (insert (format "\\newpage\n" arg)))
246                ((equal command "'s")
247                 (goto-char (match-beginning 0))
248                 (delete-char 1))
249                ((equal command "include")
250                 (latexi-strip-line)
251                 (string-match "\\.texi" arg)
252                 (insert (format "\\input{%s.latexi}\n" 
253                                 (substring arg 0 (match-beginning 0)))))
254                ((equal command "noindent")
255                 (latexi-strip-line)
256                 (insert "\\noindent\n"))
257                ((equal command "printindex")
258                 (latexi-strip-line)
259                 ;;(insert 
260                 ;; (format 
261                 ;;  "\\begin{theindex}\\input{gnus.%s}\\end{theindex}\n" arg))
262                 )
263                (t
264                 (error "Unknown command (file %s line %d): %s"
265                        file
266                        (save-excursion
267                          (widen)
268                          (1+ (count-lines (point-min) (progn
269                                                         (beginning-of-line)
270                                                         (point)))))
271                        command))))
272           ;; These are commands with {}.
273           (setq arg (match-string 5))
274           (cond 
275            ((member command '("anchor"))
276             (latexi-strip-line))
277            ((member command '("ref" "xref" "pxref"))
278             (latexi-exchange-command (concat "gnus" command) arg))
279            ((member command '("sc" "file" "dfn" "emph" "kbd" "key" "uref"
280                               "code" "samp" "var" "strong" "i"
281                               "result" "email" "env" "r" "command" "asis"
282                               "url"))
283             (goto-char (match-beginning 0))
284             (delete-char 1)
285             (insert "\\gnus"))
286            ((member command '("acronym"))
287             (latexi-exchange-command (concat "gnus" command) (downcase arg)))
288            ((member command '("copyright" "footnote" "TeX"))
289             (goto-char (match-beginning 0))
290             (delete-char 1)
291             (insert "\\"))
292            ((member command '("dots"))
293             (goto-char (match-beginning 0))
294             (delete-region (match-beginning 0) (match-end 0))
295             (insert "..."))
296            ((eq (aref command 0) ?@)
297             (goto-char (match-beginning 0))
298             (delete-char 2)
299             (insert "duppat{}"))
300            (t
301             (error "Unknown command (file %s line %d): %s"
302                    file
303                    (save-excursion
304                      (widen)
305                      (1+ (count-lines (point-min) (progn
306                                                     (beginning-of-line)
307                                                     (point)))))
308                    command))))))
309     (latexi-translate-string "$" "\\gnusdollar{}")
310     (latexi-translate-string "&" "\\gnusampersand{}")
311     (latexi-translate-string "%" "\\gnuspercent{}")
312     (latexi-translate-string "#" "\\gnushash{}")
313     (latexi-translate-string "^" "\\gnushat{}")
314     (latexi-translate-string "~" "\\gnustilde{}")
315     (latexi-translate-string "_" "\\gnusunderline{}")
316     (latexi-translate-string "¬" "\\gnusnot{}")
317     (goto-char (point-min))
318     (while (search-forward "duppat{}" nil t)
319       (replace-match "@" t t))
320     (latexi-translate-string "@@" "@")
321     (latexi-translate-string "<" "\\gnusless{}")
322     (latexi-translate-string ">" "\\gnusgreater{}")
323     (goto-char (point-min))
324     (search-forward "label{Top}" nil t)
325     (while (re-search-forward "\\\\[ntr]\\b" nil t)
326       (when (save-match-data
327               (or (not (save-excursion
328                          (search-backward "begin{verbatim}" nil t)))
329                   (> (save-excursion
330                        (search-backward "end{verbatim"))
331                      (save-excursion
332                        (search-backward "begin{verbatim}")))))
333         (goto-char (match-beginning 0))
334         (delete-char 1)
335         (insert "\\gnusbackslash{}")))
336     (latexi-translate-string "\\\\" "\\gnusbackslash{}")
337     (goto-char (point-min))
338     (while (re-search-forward "\\\\[][{}]" nil t)
339       (goto-char (match-beginning 0))
340       (delete-char 1))
341     (latexi-contributors)
342     (let ((coding-system-for-write 'iso-8859-1))
343       (write-region (point-min) (point-max) (concat file ".latexi")))))
344
345 (defun latexi-translate-string (in out)
346   (let (yes)
347     (goto-char (point-min))
348     (search-forward "label{Top}" nil t)
349     (while (search-forward in nil t)
350       (when (save-match-data
351               (or (not (save-excursion
352                          (search-backward "begin{verbatim}" nil t)))
353                   (> (save-excursion
354                        (re-search-backward "end{verbatim}\\|end{verse}"))
355                      (save-excursion
356                        (re-search-backward
357                         "begin{verbatim}\\|begin{verse}")))))
358         (replace-match out t t)))))
359
360 (defun latexi-contributors ()
361   (goto-char (point-min))
362   (when (re-search-forward "^Also thanks to the following" nil t)
363     (forward-line 2)
364     (narrow-to-region
365      (point)
366      (1- (search-forward "\n\n")))
367     (when (re-search-backward "^and" nil t)
368       (latexi-strip-line))
369     (goto-char (point-min))
370     (while (re-search-forward "[.,] *$" nil t)
371       (replace-match "" t t))
372     (goto-char (point-min))
373     (let (names)
374       (while (not (eobp))
375         (push (buffer-substring (point) (progn (end-of-line) (point)))
376               names)
377         (forward-line 1))
378       (delete-region (point-min) (point-max))
379       (insert "\\begin{tabular}{lll}\n")
380       (setq names (nreverse (delete "" names)))
381       (while names
382         (insert (pop names) " & " (or (pop names) "\\mbox{}") 
383                 " & " (or (pop names) "\\mbox{}") 
384                 "\\\\\n"))
385       (insert "\\end{tabular}\n")
386       (widen))))
387