*** empty log message ***
[bpt/emacs.git] / lisp / org / org-publish.el
CommitLineData
9542795a
CD
1;;; org-publish.el --- publish related org-mode files as a website
2
dcb8ac09 3;; Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
9542795a
CD
4
5;; Author: David O'Toole <dto@gnu.org>
699b9291
CD
6;; Maintainer: Bastien Guerry <bzg AT altern DOT org>
7;; Keywords: hypermedia, outlines, wp
8;; Version: 5.23a
9542795a 9
514a6ce6
CD
10;; This file is part of GNU Emacs.
11;;
12;; GNU Emacs is free software; you can redistribute it and/or modify
9542795a 13;; it under the terms of the GNU General Public License as published by
4fbd4750 14;; the Free Software Foundation; either version 3, or (at your option)
9542795a
CD
15;; any later version.
16
514a6ce6 17;; GNU Emacs is distributed in the hope that it will be useful,
9542795a
CD
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
514a6ce6
CD
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
9542795a
CD
25;; Boston, MA 02110-1301, USA.
26
9542795a
CD
27;;; Commentary:
28
29;; Requires at least version 4.27 of org.el
9542795a 30
699b9291
CD
31;; This program allow configurable publishing of related sets of
32;; Org-mode files as a complete website.
9542795a
CD
33;;
34;; org-publish.el can do the following:
35;;
699b9291
CD
36;; + Publish all one's org-files to HTML or LaTeX
37;; + Upload HTML, images, attachments and other files to a web server
9542795a
CD
38;; + Exclude selected private pages from publishing
39;; + Publish a clickable index of pages
699b9291 40;; + Manage local timestamps for publishing only changed files
9542795a
CD
41;; + Accept plugin functions to extend range of publishable content
42;;
43;; Special thanks to the org-mode maintainer Carsten Dominik for his
44;; ideas, enthusiasm, and cooperation.
45
46;;; Installation:
47
48;; Put org-publish.el in your load path, byte-compile it, and then add
49;; the following lines to your emacs initialization file:
50
51;; (autoload 'org-publish "org-publish" nil t)
52;; (autoload 'org-publish "org-publish-all" nil t)
53;; (autoload 'org-publish "org-publish-current-file" nil t)
54;; (autoload 'org-publish "org-publish-current-project" nil t)
55
56;; NOTE: When org-publish.el is included with org.el, those forms are
57;; already in the file org-install.el, and hence don't need to be put
58;; in your emacs initialization file in this case.
59
60;;; Usage:
61;;
62;; The program's main configuration variable is
63;; `org-publish-project-alist'. See below for example configurations
64;; with commentary.
65
66;; The main interactive functions are:
67;;
68;; M-x org-publish
69;; M-x org-publish-all
70;; M-x org-publish-current-file
71;; M-x org-publish-current-project
72
73;;;; Simple example configuration:
74
75;; (setq org-publish-project-alist
76;; (list
77;; '("org" . (:base-directory "~/org/"
78;; :base-extension "org"
79;; :publishing-directory "~/public_html"
80;; :with-section-numbers nil
81;; :table-of-contents nil
699b9291 82;; :recursive t
9542795a
CD
83;; :style "<link rel=stylesheet href=\"../other/mystyle.css\" type=\"text/css\">")))
84
85;;;; More complex example configuration:
86
87;; Imagine your *.org files are kept in ~/org, your images in
88;; ~/images, and stylesheets in ~/other. Now imagine you want to
89;; publish the files through an ssh connection to a remote host, via
90;; Tramp-mode. To maintain relative links from *.org files to /images
91;; and /other, we should replicate the same directory structure in
92;; your web server account's designated html root (in this case,
93;; assumed to be ~/html)
94
95;; Once you've done created the proper directories, you can adapt the
96;; following example configuration to your specific paths, run M-x
97;; org-publish-all, and it should publish the files to the correct
98;; directories on the web server, transforming the *.org files into
99;; HTML, and leaving other files alone.
100
101;; (setq org-publish-project-alist
102;; (list
103;; '("orgfiles" :base-directory "~/org/"
104;; :base-extension "org"
105;; :publishing-directory "/ssh:user@host:~/html/notebook/"
106;; :publishing-function org-publish-org-to-html
107;; :exclude "PrivatePage.org" ;; regexp
108;; :headline-levels 3
109;; :with-section-numbers nil
110;; :table-of-contents nil
111;; :style "<link rel=stylesheet href=\"../other/mystyle.css\" type=\"text/css\">"
112;; :auto-preamble t
113;; :auto-postamble nil)
9542795a
CD
114;; ("images" :base-directory "~/images/"
115;; :base-extension "jpg\\|gif\\|png"
116;; :publishing-directory "/ssh:user@host:~/html/images/"
117;; :publishing-function org-publish-attachment)
9542795a
CD
118;; ("other" :base-directory "~/other/"
119;; :base-extension "css"
120;; :publishing-directory "/ssh:user@host:~/html/other/"
121;; :publishing-function org-publish-attachment)
122;; ("website" :components ("orgfiles" "images" "other"))))
123
124;; For more information, see the documentation for the variable
125;; `org-publish-project-alist'.
126
127;; Of course, you don't have to publish to remote directories from
128;; within emacs. You can always just publish to local folders, and
129;; then use the synchronization/upload tool of your choice.
130
9542795a
CD
131;;; List of user-visible changes since version 1.27
132
133;; 1.78: Allow list-valued :publishing-function
134;; 1.77: Added :preparation-function, this allows you to use GNU Make etc.
135;; 1.65: Remove old "composite projects". They're redundant.
136;; 1.64: Allow meta-projects with :components
137;; 1.57: Timestamps flag is now called "org-publish-use-timestamps-flag"
138;; 1.52: Properly set default for :index-filename
139;; 1.48: Composite projects allowed.
140;; :include keyword allowed.
141;; 1.43: Index no longer includes itself in the index.
142;; 1.42: Fix "function definition is void" error
143;; when :publishing-function not set in org-publish-current-file.
144;; 1.41: Fixed bug where index isn't published on first try.
145;; 1.37: Added interactive function "org-publish". Prompts for particular
146;; project name to publish.
147;; 1.34: Added force-publish option to all interactive functions.
148;; 1.32: Fixed "index.org has changed on disk" error during index publishing.
149;; 1.30: Fixed startup error caused by (require 'em-unix)
150
151;;; Code:
152
9542795a
CD
153(eval-when-compile
154 (require 'cl))
155
1e63a7fb
GM
156(eval-and-compile
157 (unless (fboundp 'declare-function)
158 (defmacro declare-function (fn file &optional arglist fileonly))))
159
699b9291 160(require 'dired-aux)
9542795a
CD
161
162(defgroup org-publish nil
163 "Options for publishing a set of Org-mode and related files."
164 :tag "Org Publishing"
165 :group 'org)
166
9542795a
CD
167(defcustom org-publish-project-alist nil
168 "Association list to control publishing behavior.
169Each element of the alist is a publishing 'project.' The CAR of
170each element is a string, uniquely identifying the project. The
171CDR of each element is in one of the following forms:
172
173 (:property value :property value ... )
174
175OR,
176
177 (:components (\"project-1\" \"project-2\" ...))
178
179When the CDR of an element of org-publish-project-alist is in
180this second form, the elements of the list after :components are
181taken to be components of the project, which group together files
182requiring different publishing options. When you publish such a
183project with M-x org-publish, the components all publish.
184
185When a property is given a value in org-publish-project-alist, its
186setting overrides the value of the corresponding user variable
187 (if any) during publishing. However, options set within a file
188override everything.
189
190Most properties are optional, but some should always be set:
191
699b9291
CD
192 :base-directory Directory containing publishing source files
193 :base-extension Extension (without the dot!) of source files.
194 This can be a regular expression.
195 :publishing-directory Directory (possibly remote) where output
196 files will be published
9542795a
CD
197
198The :exclude property may be used to prevent certain files from
199being published. Its value may be a string or regexp matching
200file names you don't want to be published.
201
202The :include property may be used to include extra files. Its
203value may be a list of filenames to include. The filenames are
204considered relative to the publishing directory.
205
206When both :include and :exclude properties are given values, the
207exclusion step happens first.
208
209One special property controls which back-end function to use for
210publishing files in the project. This can be used to extend the
211set of file types publishable by org-publish, as well as the set
212of output formats.
213
699b9291
CD
214 :publishing-function Function to publish file. The default is
215 org-publish-org-to-html, but other
216 values are possible. May also be a
217 list of functions, in which case
218 each function in the list is invoked
219 in turn.
9542795a
CD
220
221Another property allows you to insert code that prepares a
222project for publishing. For example, you could call GNU Make on a
699b9291 223certain makefile, to ensure published files are built up to date.
9542795a 224
699b9291
CD
225 :preparation-function Function to be called before publishing
226 this project.
9542795a
CD
227
228Some properties control details of the Org publishing process,
229and are equivalent to the corresponding user variables listed in
230the right column. See the documentation for those variables to
231learn more about their use and default values.
232
699b9291
CD
233 :language org-export-default-language
234 :headline-levels org-export-headline-levels
235 :section-numbers org-export-with-section-numbers
236 :table-of-contents org-export-with-toc
237 :emphasize org-export-with-emphasize
238 :sub-superscript org-export-with-sub-superscripts
239 :TeX-macros org-export-with-TeX-macros
240 :fixed-width org-export-with-fixed-width
241 :tables org-export-with-tables
242 :table-auto-headline org-export-highlight-first-table-line
243 :style org-export-html-style
244 :convert-org-links org-export-html-link-org-files-as-html
245 :inline-images org-export-html-inline-images
246 :expand-quoted-html org-export-html-expand
247 :timestamp org-export-html-with-timestamp
248 :publishing-directory org-export-publishing-directory
249 :preamble org-export-html-preamble
250 :postamble org-export-html-postamble
251 :auto-preamble org-export-html-auto-preamble
252 :auto-postamble org-export-html-auto-postamble
253 :author user-full-name
254 :email user-mail-address
9542795a
CD
255
256The following properties may be used to control publishing of an
257index of files or summary page for a given project.
258
699b9291
CD
259 :auto-index Whether to publish an index during
260 org-publish-current-project or org-publish-all.
261 :index-filename Filename for output of index. Defaults
262 to 'index.org' (which becomes 'index.html')
263 :index-title Title of index page. Defaults to name of file.
264 :index-function Plugin function to use for generation of index.
265 Defaults to 'org-publish-org-index', which
266 generates a plain list of links to all files
267 in the project."
9542795a
CD
268 :group 'org-publish
269 :type 'alist)
270
9542795a
CD
271(defcustom org-publish-use-timestamps-flag t
272 "When non-nil, use timestamp checking to publish only changed files.
273When nil, do no timestamp checking and always publish all
274files."
275 :group 'org-publish
276 :type 'boolean)
277
9542795a
CD
278(defcustom org-publish-timestamp-directory "~/.org-timestamps/"
279 "Name of directory in which to store publishing timestamps."
280 :group 'org-publish
699b9291 281 :type 'directory)
9542795a 282
699b9291
CD
283(defcustom org-publish-before-export-hook nil
284 "Hook run before export on the Org file.
285If the functions in this hook modify the original Org buffer, the
286modified buffer will be used for export, but the buffer will be
287restored and saved back to its initial state after export."
288 :group 'org-publish
289 :type 'hook)
9542795a 290
699b9291
CD
291(defcustom org-publish-after-export-hook nil
292 "Hook run after export on the exported buffer.
293If functions in this hook modify the buffer, it will be saved."
294 :group 'org-publish
295 :type 'hook)
9542795a 296
699b9291
CD
297;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
298;;; Timestamp-related functions
9542795a
CD
299
300(defun org-publish-timestamp-filename (filename)
301 "Return path to timestamp file for filename FILENAME."
699b9291
CD
302 (while (string-match
303 (if (eq system-type 'windows-nt) "~\\|/\\|:" "~\\|/") filename)
9542795a
CD
304 (setq filename (replace-match "_" nil t filename)))
305 (concat org-publish-timestamp-directory filename ".timestamp"))
306
9542795a 307(defun org-publish-needed-p (filename)
699b9291 308 "Return `t' if FILENAME should be published."
9542795a 309 (if org-publish-use-timestamps-flag
699b9291
CD
310 (if (file-exists-p org-publish-timestamp-directory)
311 ;; first handle possible wrong timestamp directory
9542795a 312 (if (not (file-directory-p org-publish-timestamp-directory))
699b9291
CD
313 (error "Org publish timestamp: %s is not a directory"
314 org-publish-timestamp-directory)
315 ;; there is a timestamp, check if FILENAME is newer
316 (file-newer-than-file-p
317 filename (org-publish-timestamp-filename filename))))
318 ;; don't use timestamps, always return t
9542795a
CD
319 t))
320
9542795a 321(defun org-publish-update-timestamp (filename)
699b9291
CD
322 "Update publishing timestamp for file FILENAME.
323If there is no timestamp, create one."
324 (let ((timestamp-file (org-publish-timestamp-filename filename))
325 newly-created-timestamp)
326 (if (not (file-exists-p timestamp-file))
327 ;; create timestamp file if needed
328 (with-temp-buffer
329 (make-directory (file-name-directory timestamp-file) t)
330 (write-file timestamp-file)
331 (setq newly-created-timestamp t)))
332 ;; Emacs 21 doesn't have `set-file-times'
333 (if (and (fboundp 'set-file-times)
334 (not newly-created-timestamp))
335 (set-file-times timestamp-file)
336 (call-process "touch" nil 0 nil timestamp-file))))
337
338;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
339;;; Mapping files to project names
340
341(defvar org-publish-files-alist nil
342 "Alist of files and their parent project.
343Each element of this alist is of the form:
344
345 (file-name . project-name)")
346
347(defun org-publish-initialize-files-alist (&optional refresh)
348 "Set `org-publish-files-alist' if it is not set.
349Also set it if the optional argument REFRESH is non-nil."
350 (interactive "P")
351 (when (or refresh (not org-publish-files-alist))
352 (setq org-publish-files-alist
353 (org-publish-get-files org-publish-project-alist))))
354
355;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
356;;; Compatibility aliases
357
358;; Delete-dups is not in Emacs <22
359(if (fboundp 'delete-dups)
360 (defalias 'org-publish-delete-dups 'delete-dups)
361 (defun org-publish-delete-dups (list)
362 "Destructively remove `equal' duplicates from LIST.
363Store the result in LIST and return it. LIST must be a proper list.
364Of several `equal' occurrences of an element in LIST, the first
365one is kept.
366
367This is a compatibility function for Emacsen without `delete-dups'."
368 ;; Code from `subr.el' in Emacs 22:
369 (let ((tail list))
370 (while tail
371 (setcdr tail (delete (car tail) (cdr tail)))
372 (setq tail (cdr tail))))
373 list))
374
1e63a7fb
GM
375(declare-function org-publish-delete-dups "org-publish" (list))
376
699b9291
CD
377;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
378;;; Getting project information out of org-publish-project-alist
379
380(defun org-publish-get-files (projects-alist &optional no-exclusion)
381 "Return the list of all publishable files for PROJECTS-ALIST.
382If NO-EXCLUSION is non-nil, don't exclude files."
383 (let (all-files)
384 ;; add all projects
385 (mapc
386 (lambda(p)
387 (let* ((exclude (plist-get (cdr p) :exclude))
388 (files (and p (org-publish-get-base-files p exclude))))
389 ;; add all files from this project
390 (mapc (lambda(f)
391 (add-to-list 'all-files
392 (cons (expand-file-name f) (car p))))
393 files)))
394 (org-publish-expand-projects projects-alist))
395 all-files))
396
397(defun org-publish-expand-projects (projects-alist)
398 "Expand projects contained in PROJECTS-ALIST."
399 (let (without-component with-component)
400 (mapc (lambda(p)
401 (add-to-list
402 (if (plist-get (cdr p) :components)
403 'with-component 'without-component) p))
404 projects-alist)
405 (org-publish-delete-dups
406 (append without-component
407 (car (mapcar (lambda(p) (org-publish-expand-components p))
408 with-component))))))
409
410(defun org-publish-expand-components (project)
411 "Expand PROJECT into an alist of its components."
412 (let* ((components (plist-get (cdr project) :components)))
413 (org-publish-delete-dups
414 (delq nil (mapcar (lambda(c) (assoc c org-publish-project-alist))
415 components)))))
416
417(defun org-publish-get-base-files (project &optional exclude-regexp)
418 "Return a list of all files in PROJECT.
9542795a
CD
419If EXCLUDE-REGEXP is set, this will be used to filter out
420matching filenames."
699b9291
CD
421 (let* ((project-plist (cdr project))
422 (base-dir (file-name-as-directory
423 (plist-get project-plist :base-directory)))
424 (include-list (plist-get project-plist :include))
425 (recursive-p (plist-get project-plist :recursive))
426 (extension (or (plist-get project-plist :base-extension) "org"))
427 (regexp (concat "^[^\\.].*\\.\\(" extension "\\)$"))
428 alldirs allfiles files dir)
429 ;; Get all files and directories in base-directory
430 (setq files (dired-files-attributes base-dir))
431 ;; Get all subdirectories if recursive-p
432 (setq alldirs
433 (if recursive-p
434 (delq nil (mapcar (lambda(f) (if (caaddr f) (cadr f))) files))
435 (list base-dir)))
436 (while (setq dir (pop alldirs))
437 (setq files (directory-files dir t regexp))
438 ;; Exclude files
439 (setq files
440 (if (not exclude-regexp)
441 files
442 (delq nil
443 (mapcar (lambda (x)
444 (if (string-match exclude-regexp x) nil x))
445 files))))
446 ;; Include extra files
447 (let (inc)
448 (while (setq inc (pop include-list))
449 (setq files (cons (expand-file-name inc dir) files))))
450 (setq allfiles (append allfiles files)))
9542795a
CD
451 allfiles))
452
9542795a 453(defun org-publish-get-project-from-filename (filename)
699b9291
CD
454 "Return the project FILENAME belongs."
455 (let* ((project-name (cdr (assoc (expand-file-name filename)
456 org-publish-files-alist))))
457 (assoc project-name org-publish-project-alist)))
daa89d0f 458
699b9291
CD
459;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
460;;; Pluggable publishing back-end functions
daa89d0f 461
699b9291 462(defun org-publish-org-to (format plist filename pub-dir)
daa89d0f
CD
463 "Publish an org file to FORMAT.
464PLIST is the property list for the given project.
699b9291
CD
465FILENAME is the filename of the org file to be published.
466PUB-DIR is the publishing directory."
03f3cf35 467 (require 'org)
699b9291
CD
468 (unless (file-exists-p pub-dir)
469 (make-directory pub-dir t))
470 (find-file filename)
471 (let ((init-buf (current-buffer))
472 (init-point (point))
473 (init-buf-string (buffer-string)) export-buf)
474 ;; run hooks before exporting
475 (run-hooks 'org-publish-before-export-hook)
476 ;; export the possibly modified buffer
477 (setq export-buf
478 (funcall (intern (concat "org-export-as-" format))
479 (plist-get plist :headline-levels)
480 nil plist nil nil pub-dir))
481 (set-buffer export-buf)
482 ;; run hooks after export and save export
483 (and (run-hooks 'org-publish-after-export-hook)
484 (if (buffer-modified-p) (save-buffer)))
485 ;; maybe restore buffer's content
486 (set-buffer init-buf)
487 (when (buffer-modified-p init-buf)
488 (erase-buffer)
489 (insert init-buf-string)
490 (save-buffer)
491 (goto-char init-point))))
492
493(defun org-publish-org-to-latex (plist filename pub-dir)
494 "Publish an org file to LaTeX.
495See `org-publish-org-to' to the list of arguments."
496 (org-publish-org-to "latex" plist filename pub-dir))
497
498(defun org-publish-org-to-html (plist filename pub-dir)
499 "Publish an org file to HTML.
500See `org-publish-org-to' to the list of arguments."
501 (org-publish-org-to "html" plist filename pub-dir))
502
503(defun org-publish-attachment (plist filename pub-dir)
9542795a 504 "Publish a file with no transformation of any kind.
699b9291 505See `org-publish-org-to' to the list of arguments."
9542795a 506 ;; make sure eshell/cp code is loaded
699b9291 507 (eval-and-compile
5656d1bf
DN
508 (require 'eshell)
509 (require 'esh-maint)
510 (require 'em-unix))
699b9291
CD
511 (eshell/cp filename pub-dir))
512
513;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
514;;; Publishing files, sets of files, and indices
515
516(defun org-publish-file (filename &optional project)
517 "Publish file FILENAME from PROJECT."
518 (when (org-publish-needed-p filename)
519 (let* ((project
520 (or project
521 (or (org-publish-get-project-from-filename filename)
522 (if (y-or-n-p
523 (format "%s is not in a project. Re-read the list of projects files? "
524 (abbreviate-file-name filename)))
525 ;; If requested, re-initialize the list of projects files
526 (progn (org-publish-initialize-files-alist t)
527 (or (org-publish-get-project-from-filename filename)
528 (error "File %s not part of any known project"
529 (abbreviate-file-name filename))))
530 (error "Can't publish file outside of a project")))))
531 (project-plist (cdr project))
532 (publishing-function
533 (or (plist-get project-plist :publishing-function)
534 'org-publish-org-to-html))
535 (base-dir (file-name-as-directory
536 (file-truename (plist-get project-plist :base-directory))))
537 (pub-dir (file-name-as-directory
538 (file-truename (plist-get project-plist :publishing-directory))))
539 tmp-pub-dir)
540 (setq tmp-pub-dir
541 (file-name-directory
542 (concat pub-dir
543 (and (string-match (regexp-quote base-dir) filename)
544 (substring filename (match-end 0))))))
9542795a
CD
545 (if (listp publishing-function)
546 ;; allow chain of publishing functions
547 (mapc (lambda (f)
699b9291 548 (funcall f project-plist filename tmp-pub-dir))
9542795a 549 publishing-function)
699b9291
CD
550 (funcall publishing-function project-plist filename tmp-pub-dir)))
551 (org-publish-update-timestamp filename)))
552
553(defun org-publish-projects (projects)
554 "Publish all files belonging to the PROJECTS alist.
555If :auto-index is set, publish the index too."
556 (mapc
557 (lambda (project)
558 (let* ((project-plist (cdr project))
559 (exclude-regexp (plist-get project-plist :exclude))
560 (index-p (plist-get project-plist :auto-index))
561 (index-filename (or (plist-get project-plist :index-filename)
562 "index.org"))
563 (index-function (or (plist-get project-plist :index-function)
564 'org-publish-org-index))
565 (preparation-function (plist-get project-plist :preparation-function))
566 (files (org-publish-get-base-files project exclude-regexp)) file)
567 (when preparation-function (funcall preparation-function))
568 (if index-p (funcall index-function project index-filename))
569 (while (setq file (pop files))
570 (org-publish-file file project))))
571 (org-publish-expand-projects projects)))
572
573(defun org-publish-org-index (project &optional index-filename)
574 "Create an index of pages in set defined by PROJECT.
575Optionally set the filename of the index with INDEX-FILENAME.
576Default for INDEX-FILENAME is 'index.org'."
577 (let* ((project-plist (cdr project))
578 (dir (file-name-as-directory
579 (plist-get project-plist :base-directory)))
580 (exclude-regexp (plist-get project-plist :exclude))
581 (files (org-publish-get-base-files project exclude-regexp))
9542795a
CD
582 (index-filename (concat dir (or index-filename "index.org")))
583 (index-buffer (find-buffer-visiting index-filename))
584 (ifn (file-name-nondirectory index-filename))
699b9291 585 file)
9542795a
CD
586 ;; if buffer is already open, kill it to prevent error message
587 (if index-buffer
588 (kill-buffer index-buffer))
589 (with-temp-buffer
699b9291
CD
590 (while (setq file (pop files))
591 (let ((fn (file-name-nondirectory file)))
592 ;; index shouldn't index itself
593 (unless (string= fn ifn)
9542795a
CD
594 (insert (concat " + [[file:" fn "]["
595 (file-name-sans-extension fn)
596 "]]\n")))))
597 (write-file index-filename)
598 (kill-buffer (current-buffer)))))
599
699b9291
CD
600;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
601;;; Interactive publishing functions
9542795a 602
699b9291 603(defalias 'org-publish-project 'org-publish "Publish project.")
9542795a
CD
604
605;;;###autoload
699b9291
CD
606(defun org-publish (project &optional force)
607 "Publish PROJECT."
608 (interactive "P")
9542795a 609 (save-window-excursion
699b9291
CD
610 (let* ((force current-prefix-arg)
611 (org-publish-use-timestamps-flag
612 (if force nil org-publish-use-timestamps-flag)))
613 (org-publish-projects
614 (list (or project
615 (assoc (completing-read
616 "Publish project: "
617 org-publish-project-alist nil t)
618 org-publish-project-alist)))))))
9542795a
CD
619
620;;;###autoload
699b9291
CD
621(defun org-publish-all (&optional force)
622 "Publish all projects.
623With prefix argument, force publish all files."
9542795a 624 (interactive "P")
699b9291 625 (org-publish-initialize-files-alist)
9542795a 626 (save-window-excursion
699b9291
CD
627 (let ((org-publish-use-timestamps-flag
628 (if force nil org-publish-use-timestamps-flag)))
629 (org-publish-projects org-publish-project-alist))))
9542795a
CD
630
631;;;###autoload
632(defun org-publish-current-file (&optional force)
633 "Publish the current file.
634With prefix argument, force publish the file."
635 (interactive "P")
699b9291 636 (org-publish-initialize-files-alist)
9542795a
CD
637 (save-window-excursion
638 (let ((org-publish-use-timestamps-flag
699b9291 639 (if force nil org-publish-use-timestamps-flag)))
9542795a
CD
640 (org-publish-file (buffer-file-name)))))
641
9542795a 642;;;###autoload
699b9291
CD
643(defun org-publish-current-project (&optional force)
644 "Publish the project associated with the current file.
645With a prefix argument, force publishing of all files in
646the project."
9542795a 647 (interactive "P")
699b9291 648 (org-publish-initialize-files-alist)
9542795a 649 (save-window-excursion
699b9291
CD
650 (let ((project (org-publish-get-project-from-filename (buffer-file-name)))
651 (org-publish-use-timestamps-flag
652 (if force nil org-publish-use-timestamps-flag)))
653 (if (not project)
654 (error "File %s is not part of any known project" (buffer-file-name)))
655 (org-publish project))))
d5098885 656
9542795a 657(provide 'org-publish)
4fbd4750 658
699b9291 659
4fbd4750 660;; arch-tag: 72807f3c-8af0-4a6b-8dca-c3376eb25adb
9542795a 661;;; org-publish.el ends here