Merge branch 'index-generation'

This commit is contained in:
Carsten Dominik 2010-03-28 09:27:55 +02:00
commit 02b9469519
7 changed files with 275 additions and 73 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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))))

View File

@ -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

View File

@ -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)