1 ;;; muse-book.el --- Publish entries into a compilation.
3 ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5 ;; This file is not part of GNU Emacs.
7 ;; This is free software; you can redistribute it and/or modify it under
8 ;; the terms of the GNU General Public License as published by the Free
9 ;; Software Foundation; either version 2, or (at your option) any later
12 ;; This is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs; see the file COPYING. If not, write to the
19 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 ;; MA 02111-1307, 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-before-book-publish-hook nil
46 "A hook run in the book buffer before it is marked up."
50 (defcustom muse-after-book-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."
72 :type
'(choice string file
)
75 (defcustom muse-book-latex-footer
"\n\\end{document}"
76 "Footer used for publishing books to LaTeX."
77 :type
'(choice string file
)
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
))
96 (insert "\n" (muse-markup-text 'chapter
)
97 (let ((chap (muse-publishing-directive "title")))
98 (if (string= chap title
)
101 (muse-markup-text 'chapter-end
) "\n\n"))
103 (narrow-to-region beg end
)
104 (muse-publish-markup (or title
"")
105 '((100 "<\\(lisp\\)>" 0
106 muse-publish-markup-tag
)))
107 (muse-style-run-hooks :after style
))
110 (defun muse-book-publish-project
111 (project book title style
&optional output-dir force
)
112 "Publish PROJECT under the name BOOK with the given TITLE and STYLE.
113 BOOK should be a page name, i.e., letting the style determine the
114 prefix and/or suffix. The book is published to OUTPUT-DIR. If FORCE
115 is nil, the book is only published if at least one of its component
116 pages has changed since it was last published."
118 (let ((project (muse-read-project "Publish project as book: " nil t
)))
119 (append (list project
120 (read-string "Basename of book (without extension): ")
121 (read-string "Title of book: "))
122 (muse-publish-get-info))))
123 ;; Cleanup some of the arguments
124 (setq project
(muse-project project
)
125 style
(muse-style style
))
126 ;; See if any of the project's files need saving first
127 (muse-project-save-buffers project
)
128 ;; Publish each page in the project as a chapter in one large book
129 (let* ((output-path (muse-publish-output-file book output-dir style
))
130 (output-suffix (muse-style-element :osuffix style
))
132 (pats (cadr project
))
133 (publish force
) published
)
135 (setq target
(concat (file-name-sans-extension target
)
137 ;; Unless force is non-nil, determine if the book needs publishing
140 (if (symbolp (car pats
))
141 (if (eq :book-end
(car pats
))
143 (setq pats
(cddr pats
)))
144 (let ((entries (muse-project-file-entries (car pats
))))
146 (if (and (not (muse-project-private-p (cdar entries
)))
147 (file-newer-than-file-p (cdar entries
) target
))
148 (setq publish t entries nil
)
149 (setq entries
(cdr entries
)))))
150 (setq pats
(cdr pats
)))))
151 ;; Create the book from all its component parts
153 (message "The book \"%s\" is up-to-date." book
)
155 (let ((style-final (muse-style-element :final style t
))
156 (style-header (muse-style-element :header style
))
157 (style-footer (muse-style-element :footer style
))
158 (muse-publishing-current-style style
)
159 (muse-publishing-directives
160 (list (cons "title" title
)
161 (cons "date" (format-time-string "%B %e, %Y"))))
162 (muse-publishing-p t
)
163 (muse-current-project project
)
165 (run-hooks 'muse-before-book-publish-hook
)
166 (setq pats
(cadr project
))
167 (let ((style-final style-final
)
168 (style-header style-header
)
169 (style-footer style-footer
))
171 (if (symbolp (car pats
))
173 ((eq :book-part
(car pats
))
174 (insert "\n" (muse-markup-text 'part
) (cadr pats
)
175 (muse-markup-text 'part-end
) "\n")
176 (setq pats
(cddr pats
)))
177 ((eq :book-chapter
(car pats
))
178 (insert "\n" (muse-markup-text 'chapter
) (cadr pats
)
179 (muse-markup-text 'chapter-end
) "\n")
180 (setq pats
(cddr pats
)))
181 ((eq :nochapters
(car pats
))
184 ((eq :book-style
(car pats
))
185 (setq style
(muse-style (cadr pats
)))
186 (setq style-final
(muse-style-element :final style t
)
187 style-header
(muse-style-element :header style
)
188 style-footer
(muse-style-element :footer style
)
189 muse-publishing-current-style style
)
190 (setq pats
(cddr pats
)))
191 ((eq :book-funcall
(car pats
))
192 (funcall (cadr pats
))
193 (setq pats
(cddr pats
)))
194 ((eq :book-end
(car pats
))
197 (setq pats
(cddr pats
))))
198 (let ((entries (muse-project-file-entries (car pats
))))
199 (while (and entries
(car entries
) (caar entries
))
200 (unless (muse-project-private-p (cdar entries
))
201 (muse-book-publish-chapter title
(car entries
)
204 (setq entries
(cdr entries
))))
205 (setq pats
(cdr pats
)))))
206 (goto-char (point-min))
207 (if style-header
(muse-insert-file-or-string style-header book
))
208 (goto-char (point-max))
209 (if style-footer
(muse-insert-file-or-string style-footer book
))
210 (run-hooks 'muse-after-book-publish-hook
)
211 (let ((backup-inhibited t
))
212 (write-file output-path
))
214 (funcall style-final book output-path target
)))))
216 (message "The book \"%s\" has been published." book
))
219 (unless (assoc "book-latex" muse-publishing-styles
)
220 (muse-derive-style "book-latex" "latex"
221 :header
'muse-book-latex-header
222 :footer
'muse-book-latex-footer
)
224 (muse-derive-style "book-pdf" "pdf"
225 :header
'muse-book-latex-header
226 :footer
'muse-book-latex-footer
))
230 ;;; muse-book.el ends here