1 ;;; muse-book.el --- publish entries into a compilation
3 ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5 ;; This file is part of Emacs Muse. It is not part of GNU Emacs.
7 ;; Emacs Muse is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 2, or (at your
10 ;; option) any later version.
12 ;; Emacs Muse is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with Emacs Muse; see the file COPYING. If not, write to the
19 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 ;; Boston, MA 02110-1301, USA.
28 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30 ;; Muse Book Publishing
32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34 (require 'muse-publish
)
35 (require 'muse-project
)
38 (defgroup muse-book nil
39 "Module for publishing a series of Muse pages as a complete book.
40 Each page will become a separate chapter in the book, unless the
41 style keyword :nochapters is used, in which case they are all run
42 together as if one giant chapter."
45 (defcustom muse-book-before-publish-hook nil
46 "A hook run in the book buffer before it is marked up."
50 (defcustom muse-book-after-publish-hook nil
51 "A hook run in the book buffer after it is marked up."
55 (defcustom muse-book-latex-header
56 "\\documentclass{book}
58 \\usepackage[english]{babel}
59 \\usepackage[latin1]{inputenc}
60 \\usepackage[T1]{fontenc}
64 \\title{<lisp>(muse-publishing-directive \"title\")</lisp>}
65 \\author{<lisp>(muse-publishing-directive \"author\")</lisp>}
66 \\date{<lisp>(muse-publishing-directive \"date\")</lisp>}
71 "Header used for publishing books to LaTeX. This may be text or a filename."
75 (defcustom muse-book-latex-footer
"\n\\end{document}"
76 "Footer used for publishing books to LaTeX. This may be text or a filename."
80 (defun muse-book-publish-chapter (title entry style
&optional nochapters
)
81 "Publish the chapter TITLE for the file ENTRY using STYLE.
82 TITLE is a string, ENTRY is a cons of the form (PAGE-NAME .
83 FILE), and STYLE is a Muse style list.
85 This routine does the same basic work as `muse-publish-markup-buffer',
86 but treating the page as if it were a single chapter within a book."
87 (let ((muse-publishing-directives (list (cons "title" title
)))
88 (muse-publishing-current-file (cdr entry
))
90 (insert-file-contents (cdr entry
))
91 (setq end
(copy-marker (point-max) t
))
92 (muse-publish-markup-region beg end
(car entry
) style
)
94 (unless (or nochapters
95 (muse-style-element :nochapters style
))
97 (muse-insert-markup (muse-markup-text 'chapter
))
98 (insert (let ((chap (muse-publishing-directive "title")))
99 (if (string= chap title
)
102 (muse-insert-markup (muse-markup-text 'chapter-end
))
105 (narrow-to-region beg end
)
106 (muse-publish-markup (or title
"")
107 '((100 "<\\(lisp\\)>" 0
108 muse-publish-markup-tag
)))
109 (muse-style-run-hooks :after style
))
112 (defun muse-book-publish-project
113 (project book title style
&optional output-dir force
)
114 "Publish PROJECT under the name BOOK with the given TITLE and STYLE.
115 BOOK should be a page name, i.e., letting the style determine the
116 prefix and/or suffix. The book is published to OUTPUT-DIR. If FORCE
117 is nil, the book is only published if at least one of its component
118 pages has changed since it was last published."
120 (let ((project (muse-read-project "Publish project as book: " nil t
)))
121 (append (list project
122 (read-string "Basename of book (without extension): ")
123 (read-string "Title of book: "))
124 (muse-publish-get-info))))
125 ;; Cleanup some of the arguments
126 (setq project
(muse-project project
)
127 style
(muse-style style
))
128 ;; See if any of the project's files need saving first
129 (muse-project-save-buffers project
)
130 ;; Publish each page in the project as a chapter in one large book
131 (let* ((output-path (muse-publish-output-file book output-dir style
))
132 (output-suffix (muse-style-element :osuffix style
))
134 (pats (cadr project
))
135 (publish force
) published
)
137 (setq target
(concat (muse-path-sans-extension target
)
139 ;; Unless force is non-nil, determine if the book needs publishing
142 (if (symbolp (car pats
))
143 (if (eq :book-end
(car pats
))
145 (setq pats
(cddr pats
)))
146 (let ((entries (muse-project-file-entries (car pats
))))
148 (if (and (not (muse-project-private-p (cdar entries
)))
149 (file-newer-than-file-p (cdar entries
) target
))
150 (setq publish t entries nil
)
151 (setq entries
(cdr entries
)))))
152 (setq pats
(cdr pats
)))))
153 ;; Create the book from all its component parts
155 (message "The book \"%s\" is up-to-date." book
)
156 (muse-with-temp-buffer
157 (let ((style-final (muse-style-element :final style t
))
158 (style-header (muse-style-element :header style
))
159 (style-footer (muse-style-element :footer style
))
160 (muse-publishing-current-style style
)
161 (muse-publishing-directives
162 (list (cons "title" title
)
163 (cons "date" (format-time-string "%B %e, %Y"))))
164 (muse-publishing-p t
)
165 (muse-current-project project
)
167 (run-hooks 'muse-before-book-publish-hook
)
168 (setq pats
(cadr project
))
169 (let ((style-final style-final
)
170 (style-header style-header
)
171 (style-footer style-footer
))
173 (if (symbolp (car pats
))
175 ((eq :book-part
(car pats
))
177 (muse-insert-markup (muse-markup-text 'part
))
179 (muse-insert-markup (muse-markup-text 'part-end
))
181 (setq pats
(cddr pats
)))
182 ((eq :book-chapter
(car pats
))
184 (muse-insert-markup (muse-markup-text 'chapter
))
186 (muse-insert-markup (muse-markup-text 'chapter-end
))
188 (setq pats
(cddr pats
)))
189 ((eq :nochapters
(car pats
))
192 ((eq :book-style
(car pats
))
193 (setq style
(muse-style (cadr pats
)))
194 (setq style-final
(muse-style-element :final style t
)
195 style-header
(muse-style-element :header style
)
196 style-footer
(muse-style-element :footer style
)
197 muse-publishing-current-style style
)
198 (setq pats
(cddr pats
)))
199 ((eq :book-funcall
(car pats
))
200 (funcall (cadr pats
))
201 (setq pats
(cddr pats
)))
202 ((eq :book-end
(car pats
))
205 (setq pats
(cddr pats
))))
206 (let ((entries (muse-project-file-entries (car pats
))))
207 (while (and entries
(car entries
) (caar entries
))
208 (unless (muse-project-private-p (cdar entries
))
209 (muse-book-publish-chapter title
(car entries
)
212 (setq entries
(cdr entries
))))
213 (setq pats
(cdr pats
)))))
214 (goto-char (point-min))
215 (if style-header
(muse-insert-file-or-string style-header book
))
216 (goto-char (point-max))
217 (if style-footer
(muse-insert-file-or-string style-footer book
))
218 (run-hooks 'muse-after-book-publish-hook
)
219 (let ((backup-inhibited t
))
220 (write-file output-path
))
222 (funcall style-final book output-path target
)))))
224 (message "The book \"%s\" has been published." book
))
227 (unless (assoc "book-latex" muse-publishing-styles
)
228 (muse-derive-style "book-latex" "latex"
229 :header
'muse-book-latex-header
230 :footer
'muse-book-latex-footer
)
232 (muse-derive-style "book-pdf" "pdf"
233 :header
'muse-book-latex-header
234 :footer
'muse-book-latex-footer
))
238 ;;; muse-book.el ends here