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