LaTeX: escape more specials in image filenames
[muse-el.git] / lisp / muse-groff.el
blob93ede52f72c616953f174010140f5b3f8d9a5fd1
1 ;;; muse-groff.el --- publish groff -mom -mwww files
3 ;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
5 ;; Author: Andrew J. Korty (ajk AT iu DOT edu)
6 ;; Date: Tue 5-Jul-2005
8 ;; This file is part of Emacs Muse. It is not part of GNU Emacs.
10 ;; Emacs Muse is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 3, or (at your
13 ;; option) any later version.
15 ;; Emacs Muse is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;; General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with Emacs Muse; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
25 ;;; Commentary:
27 ;;; Contributors:
29 ;;; Code:
31 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33 ;; Muse Publishing Using groff -mom -mwww
35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37 (require 'muse-publish)
39 (defgroup muse-groff nil
40 "Rules for marking up a Muse file with groff -mom -mwww macros."
41 :group 'muse-publish)
43 (defcustom muse-groff-extension ".groff"
44 "Default file extension for publishing groff -mom -mwww files."
45 :type 'string
46 :group 'muse-groff)
48 (defcustom muse-groff-pdf-extension ".pdf"
49 "Default file extension for publishing groff -mom -mwww files to PDF."
50 :type 'string
51 :group 'muse-groff)
53 (defcustom muse-groff-header
54 ".TITLE \"<lisp>(muse-publishing-directive \"title\")</lisp>\"
55 .SUBTITLE \"<lisp>(muse-publishing-directive \"date\")</lisp>\"
56 .AUTHOR \"<lisp>(muse-publishing-directive \"author\")</lisp>\"
57 .PRINTSTYLE TYPESET
58 .de list
59 . LIST \\$1
60 . SHIFT_LIST \\$2
62 .PARA_INDENT 0
63 .START
64 <lisp>(and muse-publish-generate-contents \".TOC\n\")</lisp>\n"
65 "Header used for publishing groff -mom -mwww files."
66 :type '(choice string file)
67 :group 'muse-groff)
69 (defcustom muse-groff-footer " "
70 "Footer used for publishing groff -mom -mwww files."
71 :type '(choice string file)
72 :group 'muse-groff)
74 (defcustom muse-groff-markup-regexps
75 `((10400 ,(concat "\\(\n</\\(blockquote\\|center\\)>\\)?\n"
76 "\\(["
77 muse-regexp-blank
78 "]*\n\\)+\\(<\\(blockquote\\|center\\)>\n\\)?")
79 0 muse-groff-markup-paragraph))
80 "List of markup regexps for identifying regions in a Muse page.
81 For more on the structure of this list, see `muse-publish-markup-regexps'."
82 :type '(repeat (choice
83 (list :tag "Markup rule"
84 integer
85 (choice regexp symbol)
86 integer
87 (choice string function symbol))
88 function))
89 :group 'muse-groff)
91 (defcustom muse-groff-markup-functions
92 '((table . muse-groff-markup-table))
93 "An alist of style types to custom functions for that kind of text.
94 For more on the structure of this list, see
95 `muse-publish-markup-functions'."
96 :type '(alist :key-type symbol :value-type function)
97 :group 'muse-groff)
99 (defcustom muse-groff-markup-tags
101 "A list of tag specifications, for specially marking up GROFF."
102 :type '(repeat (list (string :tag "Markup tag")
103 (boolean :tag "Expect closing tag" :value t)
104 (boolean :tag "Parse attributes" :value nil)
105 (boolean :tag "Nestable" :value nil)
106 function))
107 :group 'muse-groff)
109 (defcustom muse-groff-markup-strings
110 `((image-with-desc . "\n.MPIMG -R %s.%s\n")
111 (image . "\n.MPIMG -R %s.%s\n")
112 (image-link . "\n.\\\" %s\n.MPIMG -R %s.%s")
113 (url . "\n.URL %s %s\n\\z")
114 (link . "\n.URL %s %s\n\\z")
115 (email-addr . "\f[C]%s\f[]")
116 (emdash . "\\(em")
117 (rule . "\n.RULE\n")
118 (no-break-space . "\\h")
119 (enddots . "....")
120 (dots . "...")
121 ;; (part . "\\part{")
122 ;; (part-end . "}")
123 ;; (chapter . "\\chapter{")
124 ;; (chapter-end . "}")
125 (section . ".HEAD \"")
126 (section-end . "\"")
127 (subsection . ".SUBHEAD \"")
128 (subsection-end . "\"")
129 (subsubsection . ".PARAHEAD \"")
130 (subsubsection-end . "\"")
131 ;; (footnote . "\\c\n.FOOTNOTE\n")
132 ;; (footnote-end . "\n.FOOTNOTE OFF\n")
133 ;; (footnotemark . "\\footnotemark[%d]")
134 ;; (footnotetext . "\\footnotetext[%d]{")
135 ;; (footnotetext-end . "}")
136 (begin-underline . "\n.UNDERSCORE \"")
137 (end-underline . "\"\n")
138 (begin-literal . "\\fC")
139 (end-literal . "\\fP")
140 (begin-emph . "\\fI")
141 (end-emph . "\\fP")
142 (begin-more-emph . "\\fB")
143 (end-more-emph . "\\fP")
144 (begin-most-emph . "\\f(BI")
145 (end-most-emph . "\\fP")
146 (begin-verse . ".QUOTE")
147 (end-verse . ".QUOTE OFF")
148 (begin-center . "\n.CENTER\n")
149 (end-center . "\n.QUAD L\n")
150 (begin-example . ,(concat
151 ".QUOTE_FONT CR\n.QUOTE_INDENT 1\n"".QUOTE_SIZE -2\n"
152 ".UNDERLINE_QUOTES OFF\n.QUOTE"))
153 (end-example . ".QUOTE OFF")
154 (begin-quote . ".BLOCKQUOTE")
155 (end-quote . ".BLOCKQUOTE OFF")
156 (begin-cite . "")
157 (begin-cite-author . "")
158 (begin-cite-year . "")
159 (end-cite . "")
160 (begin-uli . ".list BULLET\n.SHIFT_LIST 2m\n.ITEM\n")
161 (end-uli . "\n.LIST OFF")
162 (begin-oli . ".list DIGIT\n.SHIFT_LIST 2m\n.ITEM\n")
163 (end-oli . "\n.LIST OFF")
164 (begin-ddt . "\\fB")
165 (begin-dde . "\\fP\n.IR 4P\n")
166 (end-ddt . ".IRX CLEAR"))
167 "Strings used for marking up text.
168 These cover the most basic kinds of markup, the handling of which
169 differs little between the various styles."
170 :type '(alist :key-type symbol :value-type string)
171 :group 'muse-groff)
173 (defcustom muse-groff-markup-specials
174 '((?\\ . "\\e"))
175 "A table of characters which must be represented specially."
176 :type '(alist :key-type character :value-type string)
177 :group 'muse-groff)
179 (defun muse-groff-markup-paragraph ()
180 (let ((end (copy-marker (match-end 0) t)))
181 (goto-char (1+ (match-beginning 0)))
182 (delete-region (point) end)
183 (unless (looking-at "\.\\(\\(\\(SUB\\|PARA\\)?HEAD \\)\\|RULE$\\)")
184 (muse-insert-markup ".ALD .5v\n.PP\n.ne 2\n"))))
186 (defun muse-groff-protect-leading-chars ()
187 "Protect leading periods and apostrophes from being interpreted as
188 command characters."
189 (while (re-search-forward "^[.']" nil t)
190 (replace-match "\\\\&\\&" t)))
192 (defun muse-groff-concat-lists ()
193 "Join like lists."
194 (let ((type "")
195 arg begin)
196 (while (re-search-forward "^\.LIST[ \t]+\\(.*\\)\n" nil t)
197 (setq arg (match-string 1))
198 (if (string= arg "OFF")
199 (setq begin (match-beginning 0))
200 (if (and begin (string= type arg))
201 (delete-region begin (match-end 0))
202 (setq type arg
203 begin 0))))))
205 (defun muse-groff-fixup-dquotes ()
206 "Fixup double quotes."
207 (let ((open t))
208 (while (search-forward "\"" nil t)
209 (unless (get-text-property (match-beginning 0) 'read-only)
210 (if (and (bolp) (eq (char-before) ?\n))
211 (setq open t))
212 (if open
213 (progn
214 (replace-match "``")
215 (setq open nil))
216 (replace-match "''")
217 (setq open t))))))
219 (defun muse-groff-prepare-buffer ()
220 (goto-char (point-min))
221 (muse-groff-protect-leading-chars))
223 (defun muse-groff-munge-buffer ()
224 (goto-char (point-min))
225 (muse-groff-concat-lists))
227 (defun muse-groff-pdf-browse-file (file)
228 (shell-command (concat "open " file)))
230 (defun muse-groff-pdf-generate (file output-path final-target)
231 (muse-publish-transform-output
232 file output-path final-target "PDF"
233 (function
234 (lambda (file output-path)
235 (let ((command
236 (format
237 (concat "file=%s; ext=%s; cd %s && cp $file$ext $file.ref && "
238 "groff -mom -mwww -t $file$ext > $file.ps && "
239 "pstopdf $file.ps")
240 (file-name-sans-extension file)
241 muse-groff-extension
242 (file-name-directory output-path))))
243 (shell-command command))))
244 ".ps"))
246 ;;; Register the Muse GROFF Publisher
248 (muse-define-style "groff"
249 :suffix 'muse-groff-extension
250 :regexps 'muse-groff-markup-regexps
251 ;;; :functions 'muse-groff-markup-functions
252 :strings 'muse-groff-markup-strings
253 :tags 'muse-groff-markup-tags
254 :specials 'muse-groff-markup-specials
255 :before 'muse-groff-prepare-buffer
256 :before-end 'muse-groff-munge-buffer
257 :header 'muse-groff-header
258 :footer 'muse-groff-footer
259 :browser 'find-file)
261 (muse-derive-style "groff-pdf" "groff"
262 :final 'muse-groff-pdf-generate
263 :browser 'muse-groff-pdf-browse-file
264 :osuffix 'muse-groff-pdf-extension)
266 (provide 'muse-groff)
268 ;;; muse-groff.el ends here
270 ;; Local Variables:
271 ;; indent-tabs-mode: nil
272 ;; End: