1
;;; muse-context.el --- publish entries in ConTeXt or PDF format
3
;; Copyright (C) 2007 Free Software Foundation, Inc.
5
;; Author: Jean Magnan de Bornier (jean@bornier.net)
6
;; Created: 16-Apr-2007
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
;; This file when loaded allows you to publish .muse files as ConTeXt
14
;; files or as pdf files, using respectively the "context" and
15
;; "context-pdf" styles. It is far from being perfect, so any feedback
16
;; will be welcome and any mistake hopefully fixed.
20
;; Jean Magnan de Bornier, who based this file on muse-latex.el and
21
;; made the context, context-pdf, context-slides, and
22
;; context-slides-pdf Muse publishing styles.
28
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30
;; Muse ConTeXt Publishing
32
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34
(require 'muse-publish)
36
(defgroup muse-context nil
37
"Rules for marking up a Muse file as a ConTeXt article."
40
(defcustom muse-context-extension ".tex"
41
"Default file extension for publishing ConTeXt files."
45
(defcustom muse-context-pdf-extension ".pdf"
46
"Default file extension for publishing ConTeXt files to PDF."
50
(defcustom muse-context-pdf-program "texexec --pdf"
51
"The program that is called to generate PDF content from ConTeXt content."
55
(defcustom muse-context-pdf-cruft '(".pgf" ".tmp" ".tui" ".tuo" ".toc" ".log")
56
"Extensions of files to remove after generating PDF output successfully."
60
(defcustom muse-context-header
61
"\\setupinteraction [state=start]
64
<lisp>(muse-context-setup-bibliography)</lisp>
65
\\setuppublications[]\n
66
\\setuppublicationlist[]\n\\setupcite[]\n
68
\\startalignment[center]
70
{\\tfd <lisp>(muse-publishing-directive \"title\")</lisp>}
72
{\\tfa <lisp>(muse-publishing-directive \"author\")</lisp>}
74
{\\tfa <lisp>(muse-publishing-directive \"date\")</lisp>}
78
<lisp>(and muse-publish-generate-contents
79
(not muse-context-permit-contents-tag)
80
\"\\\\placecontent\n\\\\page[yes]\")</lisp>\n\n"
81
"Header used for publishing ConTeXt files. This may be text or a filename."
85
(defcustom muse-context-footer "<lisp>(muse-context-bibliography)</lisp>
87
"Footer used for publishing ConTeXt files. This may be text or a filename."
91
(defcustom muse-context-markup-regexps
93
(10000 "\\([0-9]+\\)-\\([0-9]+\\)" 0 "\\1--\\2")
95
;; be careful of closing quote pairs
96
(10100 "\"'" 0 "\"\\\\-'"))
97
"List of markup regexps for identifying regions in a Muse page.
98
For more on the structure of this list, see `muse-publish-markup-regexps'."
99
:type '(repeat (choice
100
(list :tag "Markup rule"
102
(choice regexp symbol)
104
(choice string function symbol))
106
:group 'muse-context)
108
(defcustom muse-context-markup-functions
109
'((table . muse-context-markup-table))
110
"An alist of style types to custom functions for that kind of text.
111
For more on the structure of this list, see
112
`muse-publish-markup-functions'."
113
:type '(alist :key-type symbol :value-type function)
114
:group 'muse-context)
116
(defcustom muse-context-markup-strings
117
'((image-with-desc . "\\placefigure[][]{%3%}{\\externalfigure[%1%.%2%]}")
118
(image . "\\placefigure[][]{}{\\externalfigure[%s.%s]}")
119
(image-link . "\\useURL[aa][%s][][%1%] \\from[aa]")
120
(anchor-ref . "\\goto{%2%}{}[%1%]")
121
(url . "\\useURL[aa][%s][][%s] \\from[aa]")
122
(url-and-desc . "\\useURL[bb][%s][][%s]\\from[bb]\\footnote{%1%}")
123
(link . "\\goto{%2%}[program(%1%)]\\footnote{%1%}")
124
(link-and-anchor . "\\useexternaldocument[%4%][%4%][] \\at{%3%, page}{}[%4%::%2%]\\footnote{%1%}")
125
(email-addr . "\\useURL[mail][mailto:%s][][%s]\\from[mail]")
126
(anchor . "\\reference[%s] ")
128
(comment-begin . "\\doifmode{comment}{")
130
(rule . "\\blank[medium]\\hrule\\blank[medium]")
131
(no-break-space . "~")
132
(enddots . "\\ldots ")
136
(chapter . "\\chapter{")
138
(section . "\\section{")
140
(subsection . "\\subsection{")
141
(subsection-end . "}")
142
(subsubsection . "\\subsubsection{")
143
(subsubsection-end . "}")
144
(section-other . "\\subsubsubject{")
145
(section-other-end . "}")
146
(footnote . "\\footnote{")
148
(footnotetext . "\\footnotetext[%d]{")
149
(begin-underline . "\\underbar{")
150
(end-underline . "}")
151
(begin-literal . "\\type{")
153
(begin-emph . "{\\em ")
155
(begin-more-emph . "{\\bf ")
156
(end-more-emph . "}")
157
(begin-most-emph . "{\\bf {\\em ")
158
(end-most-emph . "}}")
159
(begin-example . "\\starttyping")
160
(end-example . "\\stoptyping")
161
(begin-center . "\\startalignment[center]\n")
162
(end-center . "\n\\stopalignment")
163
(begin-quote . "\\startquotation\n")
164
(end-quote . "\n\\stopquotation")
165
(begin-cite . "\\cite[authoryear][")
166
(begin-cite-author . "\\cite[author][")
167
(begin-cite-year . "\\cite[year][")
169
(begin-uli . "\\startitemize\n")
170
(end-uli . "\n\\stopitemize")
171
(begin-uli-item . "\\item ")
172
(begin-oli . "\\startitemize[n]\n")
173
(end-oli . "\n\\stopitemize")
174
(begin-oli-item . "\\item ")
175
(begin-dl . "\\startitemize\n")
176
(end-dl . "\n\\stopitemize")
177
(begin-ddt . "\\head ")
179
(begin-verse . "\\blank[big]")
180
(end-verse-line . "\\par")
181
(verse-space . "\\fixedspaces ~~")
182
(end-verse . "\\blank[big]"))
183
"Strings used for marking up text.
184
These cover the most basic kinds of markup, the handling of which
185
differs little between the various styles."
186
:type '(alist :key-type symbol :value-type string)
187
:group 'muse-context)
189
(defcustom muse-context-slides-header
190
"\\usemodule[<lisp>(if (string-equal (muse-publishing-directive \"module\") nil) \"pre-01\" (muse-publishing-directive \"module\"))</lisp>]
193
\\setupinteraction [state=start]
195
\\TitlePage { <lisp>(muse-publishing-directive \"title\")</lisp>
197
\\tfa <lisp>(muse-publishing-directive \"author\")</lisp>
199
\\tfa <lisp>(muse-publishing-directive \"date\")</lisp>}"
200
"Header for publishing a presentation (slides) using ConTeXt.
201
Any of the predefined modules, which are available in the
202
tex/context/base directory, can be used by writing a \"module\"
203
directive at the top of the muse file; if no such directive is
204
provided, module pre-01 is used. Alternatively, you can use your
205
own style (\"mystyle\", in this example) by replacing
206
\"\\usemodule[]\" with \"\\input mystyle\".
208
This may be text or a filename."
210
:group 'muse-context)
212
(defcustom muse-context-slides-markup-strings
213
'((section . "\\Topic {")
214
(subsection . "\\page \n{\\bf ")
215
(subsubsection . "{\\em "))
216
"Strings used for marking up text in ConTeXt slides."
217
:type '(alist :key-type symbol :value-type string)
218
:group 'muse-context)
220
(defcustom muse-context-markup-specials-document
221
'((?\\ . "\\textbackslash")
222
(?\_ . "\\textunderscore")
223
(?\< . "\\switchtobodyfont[small]")
224
(?\> . "\\switchtobodyfont[big]")
234
"A table of characters which must be represented specially.
235
These are applied to the entire document, sans already-escaped
237
:type '(alist :key-type character :value-type string)
238
:group 'muse-context)
240
(defcustom muse-context-markup-specials-example
242
"A table of characters which must be represented specially.
243
These are applied to <example> regions.
245
With the default interpretation of <example> regions, no specials
247
:type '(alist :key-type character :value-type string)
248
:group 'muse-context)
250
(defcustom muse-context-markup-specials-literal
252
"A table of characters which must be represented specially.
253
This applies to =monospaced text= and <code> regions."
254
:type '(alist :key-type character :value-type string)
255
:group 'muse-context)
257
(defcustom muse-context-markup-specials-url
258
'((?\\ . "\\textbackslash")
268
"A table of characters which must be represented specially.
269
These are applied to URLs."
270
:type '(alist :key-type character :value-type string)
271
:group 'muse-context)
273
(defcustom muse-context-markup-specials-image
274
'((?\\ . "\\textbackslash") ; cannot find suitable replacement
282
(?\# . "\\#") ; cannot find suitable replacement
284
"A table of characters which must be represented specially.
285
These are applied to image filenames."
286
:type '(alist :key-type character :value-type string)
287
:group 'muse-context)
289
(defun muse-context-decide-specials (context)
290
"Determine the specials to escape, depending on the CONTEXT argument."
291
(cond ((memq context '(underline emphasis document url-desc verbatim))
292
muse-context-markup-specials-document)
294
muse-context-markup-specials-image)
295
((memq context '(email url))
296
muse-context-markup-specials-url)
297
((eq context 'literal)
298
muse-context-markup-specials-literal)
299
((eq context 'example)
300
muse-context-markup-specials-example)
301
(t (error "Invalid context argument '%s' in muse-context" context))))
303
(defun muse-context-markup-table ()
304
(let* ((table-info (muse-publish-table-fields (match-beginning 0)
306
(row-len (car table-info))
307
(field-list (cdr table-info)))
309
(muse-insert-markup "\\starttable[|"
310
(mapconcat 'symbol-name (make-vector row-len 'l)
311
"|") "|]\n \\HL\n \\VL ")
312
(dolist (fields field-list)
313
(let ((type (car fields)))
314
(setq fields (cdr fields))
316
(muse-insert-markup ""))
317
(insert (car fields))
318
(setq fields (cdr fields))
319
(dolist (field fields)
320
(muse-insert-markup " \\VL ")
322
(muse-insert-markup "\\VL\\NR\n \\HL\n \\VL ")
324
(muse-insert-markup " "))))
325
(muse-insert-markup "\\stoptable\n")
326
(while (search-backward "VL \\stoptable" nil t)
327
(replace-match "stoptable" nil t)))))
329
(defun muse-context-fixup-dquotes ()
330
"Fixup double quotes."
331
(goto-char (point-min))
333
(while (search-forward "\"" nil t)
334
(unless (get-text-property (match-beginning 0) 'read-only)
336
(eq (char-before) ?\n))
345
(defcustom muse-context-permit-contents-tag nil
346
"If nil, ignore <contents> tags. Otherwise, insert table of contents.
348
Most of the time, it is best to have a table of contents on the
349
first page, with a new page immediately following. To make this
350
work with documents published in both HTML and ConTeXt, we need to
351
ignore the <contents> tag.
353
If you don't agree with this, then set this option to non-nil,
354
and it will do what you expect."
356
:group 'muse-context)
358
(defun muse-context-fixup-citations ()
359
"Replace semicolons in multi-head citations with colons."
360
(goto-char (point-min))
361
(while (re-search-forward "\\\\cite.?\\[" nil t)
362
(let ((start (point))
363
(end (re-search-forward "]")))
365
(narrow-to-region start end)
366
(goto-char (point-min))
367
(while (re-search-forward ";" nil t)
368
(replace-match ","))))))
370
(defun muse-context-munge-buffer ()
371
(muse-context-fixup-dquotes)
372
(muse-context-fixup-citations)
373
(when (and muse-context-permit-contents-tag
374
muse-publish-generate-contents)
375
(goto-char (car muse-publish-generate-contents))
376
(muse-insert-markup "\\placecontent")))
378
(defun muse-context-bibliography ()
380
(goto-char (point-min))
381
(if (re-search-forward "\\\\cite.?\\[" nil t)
382
"\\completepublications[criterium=all]"
385
(defun muse-context-setup-bibliography ()
387
(goto-char (point-min))
388
(if (re-search-forward "\\\\cite.?\\[" nil t)
390
"\\usemodule[bibltx]\n\\setupbibtex [database="
391
(muse-publishing-directive "bibsource") "]")
394
(defun muse-context-pdf-browse-file (file)
395
(shell-command (concat "open " file)))
397
(defun muse-context-pdf-generate (file output-path final-target)
399
#'muse-publish-transform-output
400
file output-path final-target "PDF"
402
(lambda (file output-path)
403
(let* ((fnd (file-name-directory output-path))
404
(command (format "cd \"%s\"; %s \"%s\""
405
fnd muse-context-pdf-program
406
(file-relative-name file fnd)))
409
;; XEmacs can sometimes return a non-number result. We'll err
410
;; on the side of caution by continuing to attempt to generate
411
;; the PDF if this happens and treat the final result as
413
(while (and (< times 2)
414
(or (not (numberp result))
416
;; table of contents takes 2 passes
418
;; (muse-replace-regexp-in-string
419
;; "\\.tex\\'" ".toc" file t t))
421
(setq result (shell-command command)
423
(if (or (not (numberp result))
427
muse-context-pdf-cruft))
429
(muse-define-style "context"
430
:suffix 'muse-context-extension
431
:regexps 'muse-context-markup-regexps
432
:functions 'muse-context-markup-functions
433
:strings 'muse-context-markup-strings
434
:specials 'muse-context-decide-specials
435
:after 'muse-context-munge-buffer
436
:header 'muse-context-header
437
:footer 'muse-context-footer
440
(muse-derive-style "context-pdf" "context"
441
:final 'muse-context-pdf-generate
442
:browser 'muse-context-pdf-browse-file
443
:link-suffix 'muse-context-pdf-extension
444
:osuffix 'muse-context-pdf-extension)
446
(muse-derive-style "context-slides" "context"
447
:header 'muse-context-slides-header
448
:strings 'muse-context-slides-markup-strings)
450
(muse-derive-style "context-slides-pdf" "context-pdf"
451
:header 'muse-context-slides-header
452
:strings 'muse-context-slides-markup-strings)
454
(provide 'muse-context)
456
;;; muse-context.el ends here