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