Update all copyrights for 2010.
[muse-el.git] / lisp / muse-texinfo.el
blob4ad0092ec6591f40e5426e02452e581d6875e35e
1 ;;; muse-texinfo.el --- publish entries to Texinfo format or PDF
3 ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 ;; Free Software Foundation, Inc.
6 ;; This file is part of Emacs Muse. It is not part of GNU Emacs.
8 ;; Emacs Muse is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 3, or (at your
11 ;; option) any later version.
13 ;; Emacs Muse is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;; General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with Emacs Muse; see the file COPYING. If not, write to the
20 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 ;; Boston, MA 02110-1301, USA.
23 ;;; Commentary:
25 ;;; Contributors:
27 ;;; Code:
29 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 ;; Muse Texinfo Publishing
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 (require 'muse-publish)
36 (require 'muse-latex)
37 (require 'texnfo-upd)
39 (defgroup muse-texinfo nil
40 "Rules for marking up a Muse file as a Texinfo article."
41 :group 'muse-publish)
43 (defcustom muse-texinfo-process-natively nil
44 "If non-nil, use the Emacs `texinfmt' module to make Info files."
45 :type 'boolean
46 :require 'texinfmt
47 :group 'muse-texinfo)
49 (defcustom muse-texinfo-extension ".texi"
50 "Default file extension for publishing Texinfo files."
51 :type 'string
52 :group 'muse-texinfo)
54 (defcustom muse-texinfo-info-extension ".info"
55 "Default file extension for publishing Info files."
56 :type 'string
57 :group 'muse-texinfo)
59 (defcustom muse-texinfo-pdf-extension ".pdf"
60 "Default file extension for publishing PDF files."
61 :type 'string
62 :group 'muse-texinfo)
64 (defcustom muse-texinfo-header
65 "\\input texinfo @c -*-texinfo-*-
67 @setfilename <lisp>(concat (muse-page-name) \".info\")</lisp>
68 @settitle <lisp>(muse-publishing-directive \"title\")</lisp>
70 @documentencoding iso-8859-1
72 @iftex
73 @finalout
74 @end iftex
76 @titlepage
77 @title <lisp>(muse-publishing-directive \"title\")</lisp>
78 @author <lisp>(muse-publishing-directive \"author\")</lisp>
79 @end titlepage
81 <lisp>(and muse-publish-generate-contents \"@contents\")</lisp>
83 @node Top, Overview, , (dir)
84 @top Overview
85 @c Page published by Emacs Muse begins here\n\n"
86 "Text to prepend to a Muse page being published as Texinfo.
87 This may be text or a filename.
88 It may contain <lisp> markup tags."
89 :type 'string
90 :group 'muse-texinfo)
92 (defcustom muse-texinfo-footer
93 "\n@c Page published by Emacs Muse ends here
94 @bye\n"
95 "Text to append to a Muse page being published as Texinfo.
96 This may be text or a filename.
97 It may contain <lisp> markup tags."
98 :type 'string
99 :group 'muse-texinfo)
101 (defcustom muse-texinfo-markup-regexps nil
102 "List of markup rules for publishing a Muse page to Texinfo.
103 For more on the structure of this list, see `muse-publish-markup-regexps'."
104 :type '(repeat (choice
105 (list :tag "Markup rule"
106 integer
107 (choice regexp symbol)
108 integer
109 (choice string function symbol))
110 function))
111 :group 'muse-texinfo)
113 (defcustom muse-texinfo-markup-functions
114 '((table . muse-texinfo-markup-table)
115 (heading . muse-texinfo-markup-heading))
116 "An alist of style types to custom functions for that kind of text.
117 For more on the structure of this list, see
118 `muse-publish-markup-functions'."
119 :type '(alist :key-type symbol :value-type function)
120 :group 'muse-texinfo)
122 (defcustom muse-texinfo-markup-strings
123 '((image-with-desc . "@center @image{%1%, , , %3%, %2%}@*\n@center %3%")
124 (image . "@noindent @image{%s, , , , %s}")
125 (image-link . "@uref{%s, %s.%s}")
126 (anchor-ref . "@ref{%s, %s}")
127 (url . "@uref{%s, %s}")
128 (link . "@ref{Top, %2%, , %1%, }")
129 (link-and-anchor . "@ref{%3%, %2%, , %1%, %3%}")
130 (email-addr . "@email{%s}")
131 (anchor . "@anchor{%s} ")
132 (emdash . "---")
133 (comment-begin . "@ignore\n")
134 (comment-end . "\n@end ignore\n")
135 (rule . "@sp 1")
136 (no-break-space . "@w{ }")
137 (line-break . "@*")
138 (enddots . "@enddots{}")
139 (dots . "@dots{}")
140 (section . "@chapter ")
141 (subsection . "@section ")
142 (subsubsection . "@subsection ")
143 (section-other . "@subsubheading ")
144 (footnote . "@footnote{")
145 (footnote-end . "}")
146 (begin-underline . "_")
147 (end-underline . "_")
148 (begin-literal . "@samp{")
149 (end-literal . "}")
150 (begin-emph . "@emph{")
151 (end-emph . "}")
152 (begin-more-emph . "@strong{")
153 (end-more-emph . "}")
154 (begin-most-emph . "@strong{@emph{")
155 (end-most-emph . "}}")
156 (begin-verse . "@display\n")
157 (end-verse-line . "")
158 (verse-space . "@ @ ")
159 (end-verse . "\n@end display")
160 (begin-example . "@example\n")
161 (end-example . "\n@end example")
162 (begin-center . "@quotation\n")
163 (end-center . "\n@end quotation")
164 (begin-quote . "@quotation\n")
165 (end-quote . "\n@end quotation")
166 (begin-cite . "")
167 (begin-cite-author . "")
168 (begin-cite-year . "")
169 (end-cite . "")
170 (begin-uli . "@itemize @bullet\n")
171 (end-uli . "\n@end itemize")
172 (begin-uli-item . "@item\n")
173 (begin-oli . "@enumerate\n")
174 (end-oli . "\n@end enumerate")
175 (begin-oli-item . "@item\n")
176 (begin-dl . "@table @strong\n")
177 (end-dl . "\n@end table")
178 (begin-ddt . "@item "))
179 "Strings used for marking up text.
180 These cover the most basic kinds of markup, the handling of which
181 differs little between the various styles."
182 :type '(alist :key-type symbol :value-type string)
183 :group 'muse-texinfo)
185 (defcustom muse-texinfo-markup-specials
186 '((?@ . "@@")
187 (?{ . "@{")
188 (?} . "@}"))
189 "A table of characters which must be represented specially."
190 :type '(alist :key-type character :value-type string)
191 :group 'muse-texinfo)
193 (defcustom muse-texinfo-markup-specials-url
194 '((?@ . "@@")
195 (?{ . "@{")
196 (?} . "@}")
197 (?, . "@comma{}"))
198 "A table of characters which must be represented specially.
199 These are applied to URLs."
200 :type '(alist :key-type character :value-type string)
201 :group 'muse-texinfo)
203 (defun muse-texinfo-decide-specials (context)
204 "Determine the specials to escape, depending on CONTEXT."
205 (cond ((memq context '(underline literal emphasis email url url-desc image
206 footnote))
207 muse-texinfo-markup-specials-url)
208 (t muse-texinfo-markup-specials)))
210 (defun muse-texinfo-markup-table ()
211 (let* ((table-info (muse-publish-table-fields (match-beginning 0)
212 (match-end 0)))
213 (row-len (car table-info))
214 (field-list (cdr table-info)))
215 (when table-info
216 (muse-insert-markup "@multitable @columnfractions")
217 (dotimes (field row-len)
218 (muse-insert-markup " " (number-to-string (/ 1.0 row-len))))
219 (dolist (fields field-list)
220 (let ((type (car fields)))
221 (unless (eq type 'hline)
222 (setq fields (cdr fields))
223 (if (= type 2)
224 (muse-insert-markup "\n@headitem ")
225 (muse-insert-markup "\n@item "))
226 (insert (car fields))
227 (setq fields (cdr fields))
228 (dolist (field fields)
229 (muse-insert-markup " @tab ")
230 (insert field)))))
231 (muse-insert-markup "\n@end multitable")
232 (insert ?\n))))
234 (defun muse-texinfo-remove-links (string)
235 "Remove explicit links from STRING, replacing them with the link
236 description.
238 If no description exists for the link, use the link itself."
239 (let ((start nil))
240 (while (setq start (string-match muse-explicit-link-regexp string
241 start))
242 (setq string
243 (replace-match (or (match-string 2 string)
244 (match-string 1 string))
245 t t string)))
246 string))
248 (defun muse-texinfo-protect-wikiwords (start end)
249 "Protect all wikiwords from START to END from further processing."
250 (and (boundp 'muse-wiki-wikiword-regexp)
251 (featurep 'muse-wiki)
252 (save-excursion
253 (goto-char start)
254 (while (re-search-forward muse-wiki-wikiword-regexp end t)
255 (muse-publish-mark-read-only (match-beginning 0)
256 (match-end 0))))))
258 (defun muse-texinfo-markup-heading ()
259 (save-excursion
260 (muse-publish-markup-heading))
261 (let* ((eol (muse-line-end-position))
262 (orig-heading (buffer-substring (point) eol))
263 (beg (point)))
264 (delete-region (point) eol)
265 ;; don't allow links to be published in headings
266 (insert (muse-texinfo-remove-links orig-heading))
267 (muse-texinfo-protect-wikiwords beg (point))))
269 (defun muse-texinfo-munge-buffer ()
270 (muse-latex-fixup-dquotes)
271 (texinfo-insert-node-lines (point-min) (point-max) t)
272 (texinfo-all-menus-update t))
274 (defun muse-texinfo-pdf-browse-file (file)
275 (shell-command (concat "open " file)))
277 (defun muse-texinfo-info-generate (file output-path final-target)
278 ;; The version of `texinfmt.el' that comes with Emacs 21 doesn't
279 ;; support @documentencoding, so hack it in.
280 (when (and (not (featurep 'xemacs))
281 (eq emacs-major-version 21))
282 (put 'documentencoding 'texinfo-format
283 'texinfo-discard-line-with-args))
284 ;; Most versions of `texinfmt.el' do not support @headitem, so hack
285 ;; it in.
286 (unless (get 'headitem 'texinfo-format)
287 (put 'headitem 'texinfo-format 'texinfo-multitable-item))
288 (muse-publish-transform-output
289 file output-path final-target "Info"
290 (function
291 (lambda (file output-path)
292 (if muse-texinfo-process-natively
293 (save-window-excursion
294 (save-excursion
295 (find-file file)
296 (let ((inhibit-read-only t))
297 (texinfo-format-buffer))
298 (save-buffer)
299 (kill-buffer (current-buffer))
300 (let ((buf (get-file-buffer file)))
301 (with-current-buffer buf
302 (set-buffer-modified-p nil)
303 (kill-buffer (current-buffer))))
305 (let ((result (shell-command
306 (concat "makeinfo --enable-encoding --output="
307 output-path " " file))))
308 (if (or (not (numberp result))
309 (eq result 0))
311 nil)))))))
313 (defun muse-texinfo-pdf-generate (file output-path final-target)
314 (let ((muse-latex-pdf-program "pdftex")
315 (muse-latex-pdf-cruft '(".aux" ".cp" ".fn" ".ky" ".log" ".pg" ".toc"
316 ".tp" ".vr")))
317 (muse-latex-pdf-generate file output-path final-target)))
319 ;;; Register the Muse TEXINFO Publishers
321 (muse-define-style "texi"
322 :suffix 'muse-texinfo-extension
323 :regexps 'muse-texinfo-markup-regexps
324 :functions 'muse-texinfo-markup-functions
325 :strings 'muse-texinfo-markup-strings
326 :specials 'muse-texinfo-decide-specials
327 :after 'muse-texinfo-munge-buffer
328 :header 'muse-texinfo-header
329 :footer 'muse-texinfo-footer
330 :browser 'find-file)
332 (muse-derive-style "info" "texi"
333 :final 'muse-texinfo-info-generate
334 :link-suffix 'muse-texinfo-info-extension
335 :osuffix 'muse-texinfo-info-extension
336 :browser 'info)
338 (muse-derive-style "info-pdf" "texi"
339 :final 'muse-texinfo-pdf-generate
340 :link-suffix 'muse-texinfo-pdf-extension
341 :osuffix 'muse-texinfo-pdf-extension
342 :browser 'muse-texinfo-pdf-browse-file)
344 (provide 'muse-texinfo)
346 ;;; muse-texinfo.el ends here