Merged from mwolson@gnu.org--2006 (patch 51-52)
[muse-el.git] / lisp / muse-groff.el
blob9435c0d6391007cbe64d16a0aab0a2d9d1b86bec
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;;
3 ;; Muse Publishing Using groff -mom -mwww
4 ;;
5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 (require 'muse-publish)
9 (defgroup muse-groff nil
10 "Rules for marking up a Muse file with groff -mom -mwww macros."
11 :group 'muse-publish)
13 (defcustom muse-groff-extension ".groff"
14 "Default file extension for publishing groff -mom -mwww files."
15 :type 'string
16 :group 'muse-groff)
18 (defcustom muse-groff-pdf-extension ".pdf"
19 "Default file extension for publishing groff -mom -mwww files to PDF."
20 :type 'string
21 :group 'muse-groff)
23 (defcustom muse-groff-header
24 ".TITLE \"<lisp>(muse-publishing-directive \"title\")</lisp>\"
25 .SUBTITLE \"<lisp>(muse-publishing-directive \"date\")</lisp>\"
26 .AUTHOR \"<lisp>(muse-publishing-directive \"author\")</lisp>\"
27 .PRINTSTYLE TYPESET
28 .de list
29 . LIST \\$1
30 . SHIFT_LIST \\$2
32 .PARA_INDENT 0
33 .START
34 <lisp>(and muse-publish-generate-contents \".TOC\n\")</lisp>\n"
35 "Header used for publishing groff -mom -mwww files."
36 :type '(choice string file)
37 :group 'muse-groff)
39 (defcustom muse-groff-footer " "
40 "Footer used for publishing groff -mom -mwww files."
41 :type '(choice string file)
42 :group 'muse-groff)
44 (defcustom muse-groff-markup-regexps
45 `((10400 ,(concat "\\(\n</\\(blockquote\\|center\\)>\\)?\n"
46 "\\(["
47 muse-regexp-blank
48 "]*\n\\)+\\(<\\(blockquote\\|center\\)>\n\\)?")
49 0 muse-groff-markup-paragraph))
50 "List of markup regexps for identifying regions in a Muse page.
51 For more on the structure of this list, see `muse-publish-markup-regexps'."
52 :type '(repeat (choice
53 (list :tag "Markup rule"
54 integer
55 (choice regexp symbol)
56 integer
57 (choice string function symbol))
58 function))
59 :group 'muse-groff)
61 (defcustom muse-groff-markup-functions
62 '((table . muse-groff-markup-table))
63 "An alist of style types to custom functions for that kind of text.
64 For more on the structure of this list, see
65 `muse-publish-markup-functions'."
66 :type '(alist :key-type symbol :value-type function)
67 :group 'muse-groff)
69 (defcustom muse-groff-markup-tags
70 '()
71 "A list of tag specifications, for specially marking up GROFF."
72 :type '(repeat (list (string :tag "Markup tag")
73 (boolean :tag "Expect closing tag" :value t)
74 (boolean :tag "Parse attributes" :value nil)
75 function))
76 :group 'muse-groff)
78 (defcustom muse-groff-markup-strings
79 `((image-with-desc . "\n.MPIMG -R %s\n")
80 (image-link . "\n.MPIMG -R %s\n")
81 (url-with-image . "\n.\\\" %s\n.MPIMG -R %s")
82 (url . "\n.URL %s %s\n\\z")
83 (link . "\n.URL %s %s\n\\z")
84 (email-addr . "\f[C]%s\f[]")
85 (emdash . "\\(em")
86 (rule . "\n.RULE\n")
87 (no-break-space . "\\h")
88 (enddots . "....")
89 (dots . "...")
90 ;; (part . "\\part{")
91 ;; (part-end . "}")
92 ;; (chapter . "\\chapter{")
93 ;; (chapter-end . "}")
94 (section . ".HEAD \"")
95 (section-end . "\"")
96 (subsection . ".SUBHEAD \"")
97 (subsection-end . "\"")
98 (subsubsection . ".PARAHEAD \"")
99 (subsubsection-end . "\"")
100 ;; (footnote . "\\c\n.FOOTNOTE\n")
101 ;; (footnote-end . "\n.FOOTNOTE OFF\n")
102 ;; (footnotemark . "\\footnotemark[%d]")
103 ;; (footnotetext . "\\footnotetext[%d]{")
104 ;; (footnotetext-end . "}")
105 (begin-underline . "\n.UNDERSCORE \"")
106 (end-underline . "\"\n")
107 (begin-literal . "\\fC")
108 (end-literal . "\\fP")
109 (begin-emph . "\\fI")
110 (end-emph . "\\fP")
111 (begin-more-emph . "\\fB")
112 (end-more-emph . "\\fP")
113 (begin-most-emph . "\\f(BI")
114 (end-most-emph . "\\fP")
115 (begin-verse . ".QUOTE")
116 (end-verse . ".QUOTE OFF")
117 (begin-center . "\n.CENTER\n")
118 (end-center . "\n.QUAD L\n")
119 (begin-example . ,(concat
120 ".QUOTE_FONT CR\n.QUOTE_INDENT 1\n"".QUOTE_SIZE -2\n"
121 ".UNDERLINE_QUOTES OFF\n.QUOTE"))
122 (end-example . ".QUOTE OFF")
123 (begin-quote . ".BLOCKQUOTE")
124 (end-quote . ".BLOCKQUOTE OFF")
125 (begin-uli . ".list BULLET\n.SHIFT_LIST 2m\n.ITEM\n")
126 (end-uli . "\n.LIST OFF")
127 (begin-oli . ".list DIGIT\n.SHIFT_LIST 2m\n.ITEM\n")
128 (end-oli . "\n.LIST OFF")
129 (begin-ddt . "\\fB")
130 (begin-dde . "\\fP\n.IR 4P\n")
131 (end-ddt . ".IRX CLEAR"))
132 "Strings used for marking up text.
133 These cover the most basic kinds of markup, the handling of which
134 differs little between the various styles."
135 :type '(alist :key-type symbol :value-type string)
136 :group 'muse-groff)
138 (defcustom muse-groff-markup-specials
139 '((?\\ . "\\e"))
140 "A table of characters which must be represented specially."
141 :type '(alist :key-type character :value-type string)
142 :group 'muse-groff)
144 (defun muse-groff-markup-paragraph ()
145 (let ((end (copy-marker (match-end 0) t)))
146 (goto-char (1+ (match-beginning 0)))
147 (delete-region (point) end)
148 (unless (looking-at "\.\\(\\(\\(SUB\\|PARA\\)?HEAD \\)\\|RULE$\\)")
149 (muse-insert-markup ".ALD .5v\n.PP\n.ne 2\n"))))
151 (defun muse-groff-protect-leading-chars ()
152 "Protect leading periods and apostrophes from being interpreted as
153 command characters."
154 (while (re-search-forward "^[.']" nil t)
155 (replace-match "\\\\&\\&" t)))
157 (defun muse-groff-concat-lists ()
158 "Join like lists."
159 (let ((type "")
160 arg begin)
161 (while (re-search-forward "^\.LIST[ \t]+\\(.*\\)\n" nil t)
162 (setq arg (match-string 1))
163 (if (string= arg "OFF")
164 (setq begin (match-beginning 0))
165 (if (and begin (string= type arg))
166 (delete-region begin (match-end 0))
167 (setq type arg
168 begin 0))))))
170 (defun muse-groff-fixup-dquotes ()
171 "Fixup double quotes."
172 (let ((open t))
173 (while (search-forward "\"" nil t)
174 (unless (get-text-property (match-beginning 0) 'read-only)
175 (if (and (bolp) (eq (char-before) ?\n))
176 (setq open t))
177 (if open
178 (progn
179 (replace-match "``")
180 (setq open nil))
181 (replace-match "''")
182 (setq open t))))))
184 (defun muse-groff-prepare-buffer ()
185 (goto-char (point-min))
186 (muse-groff-protect-leading-chars))
188 (defun muse-groff-finalize-buffer ()
189 (goto-char (point-min))
190 (muse-groff-concat-lists))
192 (defun muse-groff-pdf-browse-file (file)
193 (shell-command (concat "open " file)))
195 (defun muse-groff-pdf-generate (file output-path final-target)
196 (muse-publish-transform-output
197 file output-path final-target "PDF"
198 (function
199 (lambda (file output-path)
200 (let ((command
201 (format
202 (concat "file=%s; ext=%s; cd %s && cp $file$ext $file.ref && "
203 "groff -mom -mwww -t $file$ext > $file.ps && "
204 "pstopdf $file.ps")
205 (file-name-sans-extension file)
206 muse-groff-extension
207 (file-name-directory output-path))))
208 (shell-command command))))
209 ".ps"))
211 (unless (assoc "groff" muse-publishing-styles)
212 (muse-define-style "groff"
213 :suffix 'muse-groff-extension
214 :regexps 'muse-groff-markup-regexps
215 ;;; :functions 'muse-groff-markup-functions
216 :strings 'muse-groff-markup-strings
217 :tags 'muse-groff-markup-tags
218 :specials 'muse-groff-markup-specials
219 :before 'muse-groff-prepare-buffer
220 :after 'muse-groff-finalize-buffer
221 :header 'muse-groff-header
222 :footer 'muse-groff-footer
223 :browser 'find-file)
225 (muse-derive-style "groff-pdf" "groff"
226 :final 'muse-groff-pdf-generate
227 :browser 'muse-groff-pdf-browse-file
228 :osuffix 'muse-groff-pdf-extension))
230 (provide 'muse-groff)
232 ;;; muse-groff.el ends here
234 ;; Local Variables:
235 ;; indent-tabs-mode: nil
236 ;; End: