summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2010-02-25 07:31:29 +0100
committerCarsten Dominik <carsten.dominik@gmail.com>2010-03-28 09:27:33 +0200
commit4892c8899e5b99d041836749fb2d1458971be55d (patch)
tree47a3c83e4a9efc5968dd39458078b03e5e07e5c9
parent6b8632e2c3b1573f12e8eae2c1d4a15e31ab9ffe (diff)
downloadorg-mode-4892c8899e5b99d041836749fb2d1458971be55d.tar.gz
Implement index generation during export
This new code will search #+INDEX lines in the buffer. For LaTeX, it will simple convert these into LaTeX \index{} commands. For other backends, it will copy thee entries to a new file, with extension orgx. These files can then later be post-processed to create the index.
-rw-r--r--doc/ChangeLog5
-rw-r--r--doc/org.texi90
-rwxr-xr-xlisp/ChangeLog11
-rw-r--r--lisp/org-ascii.el5
-rw-r--r--lisp/org-exp.el23
-rw-r--r--lisp/org-latex.el5
-rw-r--r--lisp/org-publish.el209
7 files changed, 275 insertions, 73 deletions
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 7f9a514..b9fb625 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,8 @@
+2010-03-28 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * org.texi (Index entries): New section.
+ (Generating an index): New section.
+
2010-03-27 Carsten Dominik <carsten.dominik@gmail.com>
* org.texi (Column width and alignment): Document that <N> now
diff --git a/doc/org.texi b/doc/org.texi
index 671df0c..bc57b93 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -304,6 +304,7 @@ Markup for rich export
* Images and tables:: Tables and Images will be included
* Literal examples:: Source code examples with special formatting
* Include files:: Include additional files into a document
+* Index entries::
* Macro replacement:: Use macros to create complex output
* Embedded LaTeX:: LaTeX can be freely used inside Org documents
@@ -385,7 +386,8 @@ Configuration
* Publishing action:: Setting the function doing the publishing
* Publishing options:: Tweaking HTML export
* Publishing links:: Which links keep working after publishing?
-* Project page index:: Publishing a list of project files
+* Sitemap:: Generating a list of all pages
+* Generating an index:: An index that reaches across pages
Sample configuration
@@ -8199,6 +8201,7 @@ summarizes the markup rules used in an Org-mode buffer.
* Images and tables:: Tables and Images will be included
* Literal examples:: Source code examples with special formatting
* Include files:: Include additional files into a document
+* Index entries::
* Macro replacement:: Use macros to create complex output
* Embedded LaTeX:: LaTeX can be freely used inside Org documents
@end menu
@@ -8550,7 +8553,7 @@ label is stored as a link @samp{(label)}, for retrieval with @kbd{C-c C-l}.
@end table
-@node Include files, Macro replacement, Literal examples, Markup
+@node Include files, Index entries, Literal examples, Markup
@section Include files
@cindex include files, markup rules
@@ -8581,8 +8584,25 @@ the selected markup. For example, to include a file as an item, use
Visit the include file at point.
@end table
+@node Index entries, Macro replacement, Include files, Markup
+@section Index enries
+@cindex index entries, for publishing
-@node Macro replacement, Embedded LaTeX, Include files, Markup
+You can specify entries that will be used for generating an index during
+publishing. This is done by lines starting with @code{#+INDEX}. An entry
+the contains an exclamation mark will create a sub item. See @ref{Generating
+an index} for more information.
+
+@example
+* Curriculum Vitae
+#+INDEX: CV
+#+INDEX: Application!CV
+@end example
+
+
+
+
+@node Macro replacement, Embedded LaTeX, Index entries, Markup
@section Macro replacement
@cindex macro replacement, during export
@cindex #+MACRO
@@ -10098,7 +10118,8 @@ and many other properties of a project.
* Publishing action:: Setting the function doing the publishing
* Publishing options:: Tweaking HTML export
* Publishing links:: Which links keep working after publishing?
-* Project page index:: Publishing a list of project files
+* Sitemap:: Generating a list of all pages
+* Generating an index:: An index that reaches across pages
@end menu
@node Project alist, Sources and destinations, Configuration, Configuration
@@ -10144,13 +10165,15 @@ publish to a webserver using a file name syntax appropriate for
the Emacs @file{tramp} package. Or you can publish to a local directory and
use external tools to upload your website (@pxref{Uploading files}).
@item @code{:preparation-function}
-@tab Function called before starting the publishing process, for example, to
-run @code{make} for updating files to be published. The project property
-list is scoped into this call as the variable @code{project-plist}.
+@tab Function or list of functions to be called before starting the
+publishing process, for example, to run @code{make} for updating files to be
+published. The project property list is scoped into this call as the
+variable @code{project-plist}.
@item @code{:completion-function}
-@tab Function called after finishing the publishing process, for example, to
-change permissions of the resulting files. The project property list is
-scoped into this call as the variable @code{project-plist}.
+@tab Function or list of functions called after finishing the publishing
+process, for example, to change permissions of the resulting files. The
+project property list is scoped into this call as the variable
+@code{project-plist}.
@end multitable
@noindent
@@ -10337,7 +10360,7 @@ its setting overrides the value of the corresponding user variable (if
any) during publishing. Options set within a file (@pxref{Export
options}), however, override everything.
-@node Publishing links, Project page index, Publishing options, Configuration
+@node Publishing links, Sitemap, Publishing options, Configuration
@subsection Links between published files
@cindex links, publishing
@@ -10374,31 +10397,48 @@ description into the HTML file, but no link. One option for this
function is @code{org-publish-validate-link} which checks if the given
file is part of any project in @code{org-publish-project-alist}.
-@node Project page index, , Publishing links, Configuration
-@subsection Project page index
-@cindex index, of published pages
+@node Sitemap, Generating an index, Publishing links, Configuration
+@subsection Generating a sitemap
+@cindex sitemap, of published pages
-The following properties may be used to control publishing of an
-index of files or a summary page for a given project.
+The following properties may be used to control publishing of
+a map of files for a given project.
@multitable @columnfractions 0.25 0.75
-@item @code{:auto-index}
-@tab When non-nil, publish an index during @code{org-publish-current-project}
+@item @code{:auto-sitemap}
+@tab When non-nil, publish a sitemap during @code{org-publish-current-project}
or @code{org-publish-all}.
-@item @code{:index-filename}
-@tab Filename for output of index. Defaults to @file{sitemap.org} (which
+@item @code{:sitemap-filename}
+@tab Filename for output of sitemap. Defaults to @file{sitemap.org} (which
becomes @file{sitemap.html}).
-@item @code{:index-title}
-@tab Title of index page. Defaults to name of file.
+@item @code{:sitemap-title}
+@tab Title of sitemap page. Defaults to name of file.
-@item @code{:index-function}
-@tab Plug-in function to use for generation of index.
-Defaults to @code{org-publish-org-index}, which generates a plain list
+@item @code{:sitemap-function}
+@tab Plug-in function to use for generation of the sitemap.
+Defaults to @code{org-publish-org-sitemap}, which generates a plain list
of links to all files in the project.
@end multitable
+@node Generating an index, , Sitemap, Configuration
+@subsection Generating an index
+@cindex index, in a publishing project
+
+Org-mode can generate an index across the files of a publishing project.
+
+@multitable @columnfractions 0.25 0.75
+@item @code{:makeindex}
+@tab When non-nil, generate in index in the file @file{theindex.org} and
+publish it as @file{theindex.html}.
+@end multitable
+
+The file will be create when first publishing a project with the
+@code{:makeindex} set. The file only contains a statement @code{#+include:
+"theindex.inc"}. You can then built around this include statement by adding
+a title, style information etc.
+
@node Uploading files, Sample configuration, Configuration, Publishing
@section Uploading files
@cindex rsync
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 848c42c..e492ad3 100755
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,14 @@
+2010-03-28 Carsten Dominik <carsten.dominik@gmail.com>
+
+ * org-publish.el (org-publish-sanitize-plist): New function to
+ rename "index" properties to "sitemap". Do this renaming
+ globally.
+ (org-publish-with-aux-preprocess-maybe): New macro.
+ (org-publish-org-to-pdf, org-publish-org-to-html): Use the new
+ macro.
+ (org-publish-aux-preprocess)
+ (org-publish-index-generate-theindex.inc): New function.
+
2010-03-27 Carsten Dominik <carsten.dominik@gmail.com>
* org-table.el (org-table-align): Interpret <N> at fixed width,
diff --git a/lisp/org-ascii.el b/lisp/org-ascii.el
index 633958c..00840fa 100644
--- a/lisp/org-ascii.el
+++ b/lisp/org-ascii.el
@@ -189,6 +189,11 @@ publishing directory."
(if subtree-p
(org-export-add-subtree-options opt-plist rbeg)
opt-plist)))
+ ;; The following two are dynamically scoped into other
+ ;; routines below.
+ (org-current-export-dir
+ (or pub-dir (org-export-directory :html opt-plist)))
+ (org-current-export-file buffer-file-name)
(custom-times org-display-custom-times)
(org-ascii-current-indentation '(0 . 0))
(level 0) line txt
diff --git a/lisp/org-exp.el b/lisp/org-exp.el
index f4e89f4..0add47f 100644
--- a/lisp/org-exp.el
+++ b/lisp/org-exp.el
@@ -396,6 +396,11 @@ This is run after selection of trees to be exported has happened.
This selection includes tags-based selection, as well as removal
of commented and archived trees.")
+(defvar org-export-preprocess-after-headline-targets-hook nil
+ "Hook for preprocessing export buffer.
+This is run just after the headline targets have been defined and
+the target-alist has been set up.")
+
(defvar org-export-preprocess-before-selecting-backend-code-hook nil
"Hook for preprocessing an export buffer.
This is run just before backend-specific blocks get selected.")
@@ -1296,6 +1301,8 @@ translations. There is currently no way for users to extend this.")
"Alist of targets with invisible aliases.")
(defvar org-export-preferred-target-alist nil
"Alist of section id's with preferred aliases.")
+(defvar org-export-id-target-alist nil
+ "Alist of section id's with preferred aliases.")
(defvar org-export-code-refs nil
"Alist of code references and line numbers")
@@ -1320,9 +1327,10 @@ on this string to produce the exported version."
(outline-regexp "\\*+ ")
target-alist rtn)
- (setq org-export-target-aliases nil)
- (setq org-export-preferred-target-alist nil)
- (setq org-export-code-refs nil)
+ (setq org-export-target-aliases nil
+ org-export-preferred-target-alist nil
+ org-export-id-target-alist nil
+ org-export-code-refs nil)
(with-current-buffer (get-buffer-create " org-mode-tmp")
(erase-buffer)
@@ -1379,6 +1387,8 @@ on this string to produce the exported version."
;; Find all headings and compute the targets for them
(setq target-alist (org-export-define-heading-targets target-alist))
+ (run-hooks 'org-export-preprocess-after-headline-targets-hook)
+
;; Find HTML special classes for headlines
(org-export-remember-html-container-classes)
@@ -1517,7 +1527,12 @@ The new targets are added to TARGET-ALIST, which is also returned."
(if (not (assoc last-section-target
org-export-preferred-target-alist))
(push (cons last-section-target id)
- org-export-preferred-target-alist))))
+ org-export-preferred-target-alist)))
+ (when (equal (match-string 1) "ID")
+ (if (not (assoc last-section-target
+ org-export-id-target-alist))
+ (push (cons last-section-target (concat "ID-" id))
+ org-export-id-target-alist))))
(setq level (org-reduced-level
(save-excursion (goto-char (point-at-bol))
(org-outline-level))))
diff --git a/lisp/org-latex.el b/lisp/org-latex.el
index 2ba6e31..3f0e3d7 100644
--- a/lisp/org-latex.el
+++ b/lisp/org-latex.el
@@ -636,6 +636,11 @@ when PUB-DIR is set, use this as the publishing directory."
opt-plist)))
;; Make sure the variable contains the updated values.
(org-export-latex-options-plist (setq org-export-opt-plist opt-plist))
+ ;; The following two are dynamically scoped into other
+ ;; routines below.
+ (org-current-export-dir
+ (or pub-dir (org-export-directory :html opt-plist)))
+ (org-current-export-file buffer-file-name)
(title (or (and subtree-p (org-export-get-title-from-subtree))
(plist-get opt-plist :title)
(and (not
diff --git a/lisp/org-publish.el b/lisp/org-publish.el
index d8c248c..a27cea1 100644
--- a/lisp/org-publish.el
+++ b/lisp/org-publish.el
@@ -31,7 +31,7 @@
;; + Publish all one's org-files to HTML or PDF
;; + Upload HTML, images, attachments and other files to a web server
;; + Exclude selected private pages from publishing
-;; + Publish a clickable index of pages
+;; + Publish a clickable sitemap of pages
;; + Manage local timestamps for publishing only changed files
;; + Accept plugin functions to extend range of publishable content
;;
@@ -39,6 +39,16 @@
;;; Code:
+
+(defun org-publish-sanitize-plist (plist)
+ (mapcar (lambda (x)
+ (or (cdr (assoq x '((:index-filename . :sitemap-filename)
+ (:index-title . :sitemap-title)
+ (:index-function . :sitemap-function)
+ (:index-style . :sitemap-style)
+ (:auto-index . :auto-sitemap))))
+ x))))
+
(eval-when-compile
(require 'cl))
(require 'org)
@@ -112,9 +122,11 @@ project for publishing. For example, you could call GNU Make on a
certain makefile, to ensure published files are built up to date.
:preparation-function Function to be called before publishing
- this project.
+ this project. This may also be a list
+ of functions.
:completion-function Function to be called after publishing
- this project.
+ this project. This may also be a list
+ of functions.
Some properties control details of the Org publishing process,
and are equivalent to the corresponding user variables listed in
@@ -144,22 +156,22 @@ learn more about their use and default values.
:author `user-full-name'
:email `user-mail-address'
-The following properties may be used to control publishing of an
-index of files or summary page for a given project.
+The following properties may be used to control publishing of a
+sitemap of files or summary page for a given project.
- :auto-index Whether to publish an index during
+ :auto-sitemap Whether to publish a sitemap during
`org-publish-current-project' or `org-publish-all'.
- :index-filename Filename for output of index. Defaults
+ :sitemap-filename Filename for output of sitemap. Defaults
to 'sitemap.org' (which becomes 'sitemap.html').
- :index-title Title of index page. Defaults to name of file.
- :index-function Plugin function to use for generation of index.
- Defaults to `org-publish-org-index', which
+ :sitemap-title Title of sitemap page. Defaults to name of file.
+ :sitemap-function Plugin function to use for generation of sitemap.
+ Defaults to `org-publish-org-sitemap', which
generates a plain list of links to all files
in the project.
- :index-style Can be `list' (index is just an itemized list
+ :sitemap-style Can be `list' (sitemap is just an itemized list
of the titles of the files involved) or
`tree' (the directory structure of the source
- files is reflected in the index). Defaults to
+ files is reflected in the sitemap). Defaults to
`tree'."
:group 'org-publish
:type 'alist)
@@ -439,20 +451,32 @@ PUB-DIR is the publishing directory."
(unless visiting
(kill-buffer init-buf))))))
+(defmacro org-publish-with-aux-preprocess-maybe (&rest body)
+ "Execute BODY with a modified hook to preprocess for index."
+ `(let ((org-export-preprocess-after-headline-targets-hook
+ (if (plist-get project-plist :makeindex)
+ (cons 'org-publish-aux-preprocess
+ org-export-preprocess-after-headline-targets-hook)
+ org-export-preprocess-after-headline-targets-hook)))
+ ,@body))
+
(defun org-publish-org-to-latex (plist filename pub-dir)
"Publish an org file to LaTeX.
See `org-publish-org-to' to the list of arguments."
- (org-publish-org-to "latex" plist filename pub-dir))
+ (org-publish-with-aux-preprocess-maybe
+ (org-publish-org-to "latex" plist filename pub-dir)))
(defun org-publish-org-to-pdf (plist filename pub-dir)
"Publish an org file to PDF (via LaTeX).
See `org-publish-org-to' to the list of arguments."
- (org-publish-org-to "pdf" plist filename pub-dir))
+ (org-publish-with-aux-preprocess-maybe
+ (org-publish-org-to "pdf" plist filename pub-dir)))
(defun org-publish-org-to-html (plist filename pub-dir)
"Publish an org file to HTML.
See `org-publish-org-to' to the list of arguments."
- (org-publish-org-to "html" plist filename pub-dir))
+ (org-publish-with-aux-preprocess-maybe
+ (org-publish-org-to "html" plist filename pub-dir)))
(defun org-publish-org-to-org (plist filename pub-dir)
"Publish an org file to HTML.
@@ -518,31 +542,39 @@ See `org-publish-org-to' to the list of arguments."
(defun org-publish-projects (projects)
"Publish all files belonging to the PROJECTS alist.
-If :auto-index is set, publish the index too."
+If :auto-sitemap is set, publish the sitemap too.
+If :makeindex is set, also produce a file theindex.org."
(mapc
(lambda (project)
(let*
((project-plist (cdr project))
(exclude-regexp (plist-get project-plist :exclude))
- (index-p (plist-get project-plist :auto-index))
- (index-filename (or (plist-get project-plist :index-filename)
- "sitemap.org"))
- (index-function (or (plist-get project-plist :index-function)
- 'org-publish-org-index))
+ (sitemap-p (plist-get project-plist :auto-sitemap))
+ (sitemap-filename (or (plist-get project-plist :sitemap-filename)
+ "sitemap.org"))
+ (sitemap-function (or (plist-get project-plist :sitemap-function)
+ 'org-publish-org-sitemap))
(preparation-function (plist-get project-plist :preparation-function))
(completion-function (plist-get project-plist :completion-function))
(files (org-publish-get-base-files project exclude-regexp)) file)
- (when preparation-function (funcall preparation-function))
- (if index-p (funcall index-function project index-filename))
+ (when preparation-function (run-hooks 'preparation-function))
+ (if sitemap-p (funcall sitemap-function project sitemap-filename))
(while (setq file (pop files))
(org-publish-file file project))
- (when completion-function (funcall completion-function))))
+ (when (plist-get project-plist :makeindex)
+ (org-publish-index-generate-theindex.inc
+ (plist-get project-plist :base-directory))
+ (org-publish-file (expand-file-name
+ "theindex.org"
+ (plist-get project-plist :base-directory))
+ project))
+ (when completion-function (run-hooks 'completion-function))))
(org-publish-expand-projects projects)))
-(defun org-publish-org-index (project &optional index-filename)
- "Create an index of pages in set defined by PROJECT.
-Optionally set the filename of the index with INDEX-FILENAME.
-Default for INDEX-FILENAME is 'sitemap.org'."
+(defun org-publish-org-sitemap (project &optional sitemap-filename)
+ "Create an sitemap of pages in set defined by PROJECT.
+Optionally set the filename of the sitemap with SITEMAP-FILENAME.
+Default for SITEMAP-FILENAME is 'sitemap.org'."
(let* ((project-plist (cdr project))
(dir (file-name-as-directory
(plist-get project-plist :base-directory)))
@@ -550,28 +582,28 @@ Default for INDEX-FILENAME is 'sitemap.org'."
(indent-str (make-string 2 ?\ ))
(exclude-regexp (plist-get project-plist :exclude))
(files (nreverse (org-publish-get-base-files project exclude-regexp)))
- (index-filename (concat dir (or index-filename "sitemap.org")))
- (index-title (or (plist-get project-plist :index-title)
- (concat "Index for project " (car project))))
- (index-style (or (plist-get project-plist :index-style)
+ (sitemap-filename (concat dir (or sitemap-filename "sitemap.org")))
+ (sitemap-title (or (plist-get project-plist :sitemap-title)
+ (concat "Sitemap for project " (car project))))
+ (sitemap-style (or (plist-get project-plist :sitemap-style)
'tree))
- (visiting (find-buffer-visiting index-filename))
- (ifn (file-name-nondirectory index-filename))
- file index-buffer)
- (with-current-buffer (setq index-buffer
- (or visiting (find-file index-filename)))
+ (visiting (find-buffer-visiting sitemap-filename))
+ (ifn (file-name-nondirectory sitemap-filename))
+ file sitemap-buffer)
+ (with-current-buffer (setq sitemap-buffer
+ (or visiting (find-file sitemap-filename)))
(erase-buffer)
- (insert (concat "#+TITLE: " index-title "\n\n"))
+ (insert (concat "#+TITLE: " sitemap-title "\n\n"))
(while (setq file (pop files))
(let ((fn (file-name-nondirectory file))
(link (file-relative-name file dir))
(oldlocal localdir))
- ;; index shouldn't index itself
- (unless (equal (file-truename index-filename)
+ ;; sitemap shouldn't list itself
+ (unless (equal (file-truename sitemap-filename)
(file-truename file))
- (if (eq index-style 'list)
- (message "Generating list-style index for %s" index-title)
- (message "Generating tree-style index for %s" index-title)
+ (if (eq sitemap-style 'list)
+ (message "Generating list-style sitemap for %s" sitemap-title)
+ (message "Generating tree-style sitemap for %s" sitemap-title)
(setq localdir (concat (file-name-as-directory dir)
(file-name-directory link)))
(unless (string= localdir oldlocal)
@@ -600,7 +632,7 @@ Default for INDEX-FILENAME is 'sitemap.org'."
(org-publish-find-title file)
"]]\n")))))
(save-buffer))
- (or visiting (kill-buffer index-buffer))))
+ (or visiting (kill-buffer sitemap-buffer))))
(defun org-publish-find-title (file)
"Find the title of file in project."
@@ -656,6 +688,7 @@ directory and force publishing all files."
(if force nil org-publish-use-timestamps-flag)))
(org-publish-projects org-publish-project-alist))))
+
;;;###autoload
(defun org-publish-current-file (&optional force)
"Publish the current file.
@@ -682,6 +715,94 @@ the project."
(error "File %s is not part of any known project" (buffer-file-name)))
(org-publish project))))
+
+;;; Index generation
+
+(defun org-publish-aux-preprocess ()
+ "Find index entries and write them to an .orgx file."
+ (let (entry index)
+ (goto-char (point-min))
+ (while
+ (and
+ (re-search-forward "^[ \t]*#\\+index:[ \t]*\\(.*?\\)[ \t]*$" nil t)
+ (> (match-end 1) (match-beginning 1)))
+ (setq entry (match-string 1))
+ (when (eq backend 'latex)
+ (replace-match (format "\\index{%s}" entry) t t))
+ (save-excursion
+ (org-back-to-heading t)
+ (setq target (get-text-property (point) 'target))
+ (setq target (or (cdr (assoc target org-export-preferred-target-alist))
+ (cdr (assoc target org-export-id-target-alist))
+ target))
+ (push (cons entry target) index)))
+ (with-temp-file
+ (concat (file-name-sans-extension org-current-export-file) ".orgx")
+ (dolist (entry (nreverse index))
+ (insert (format "INDEX: (%s) %s\n" (cdr entry) (car entry)))))))
+
+(defun org-publish-index-generate-theindex.inc (directory)
+ "Generate the index from all .orgx files in the current directory and below."
+ (require 'find-lisp)
+ (let* ((fulldir (file-name-as-directory
+ (expand-file-name directory)))
+ (full-files (find-lisp-find-files directory "\\.orgx\\'"))
+ (re (concat "\\`" fulldir))
+ (files (mapcar (lambda (f) (if (string-match re f)
+ (substring f (match-end 0))
+ f))
+ full-files))
+ (default-directory directory)
+ index origfile buf target entry ibuffer
+ main last-main letter last-letter)
+ ;; `files' contains the list of relative file names
+ (dolist (file files)
+ (setq origfile (substring file 0 -1))
+ (setq buf (find-file-noselect file))
+ (with-current-buffer buf
+ (goto-char (point-min))
+ (while (re-search-forward "^INDEX: (\\(.*?\\)) \\(.*\\)" nil t)
+ (setq target (match-string 1)
+ entry (match-string 2))
+ (push (list entry origfile target) index)))
+ (kill-buffer buf))
+ (setq index (sort index (lambda (a b) (string< (downcase (car a))
+ (downcase (car b))))))
+ (setq ibuffer (find-file-noselect (expand-file-name "theindex.inc" directory)))
+ (with-current-buffer ibuffer
+ (erase-buffer)
+ (insert "* Index\n")
+ (setq last-letter nil)
+ (dolist (idx index)
+ (setq entry (car idx) file (nth 1 idx) target (nth 2 idx))
+ (setq letter (upcase (substring entry 0 1)))
+ (when (not (equal letter last-letter))
+ (insert "** " letter "\n")
+ (setq last-letter letter))
+ (if (string-match "!" entry)
+ (setq main (substring entry 0 (match-beginning 0))
+ sub (substring entry (match-end 0)))
+ (setq main nil sub nil last-main nil))
+ (when (and main (not (equal main last-main)))
+ (insert " - " main "\n")
+ (setq last-main main))
+ (setq link (concat "[[file:" file "::#" target "]"
+ "[" (or sub entry) "]]"))
+ (if (and main sub)
+ (insert " - " link "\n")
+ (insert " - " link "\n")))
+ (save-buffer))
+ (kill-buffer ibuffer)
+
+ (let ((index-file (expand-file-name "theindex.org" directory)))
+ (unless (file-exists-p index-file)
+ (setq ibuffer (find-file-noselect index-file))
+ (with-current-buffer ibuffer
+ (erase-buffer)
+ (insert "\n\n#+include: \"theindex.inc\"\n\n")
+ (save-buffer))
+ (kill-buffer ibuffer)))))
+
(provide 'org-publish)