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