Function: org-publish-index-generate-theindex

org-publish-index-generate-theindex is a byte-compiled function defined in ox-publish.el.gz.

Signature

(org-publish-index-generate-theindex PROJECT DIRECTORY)

Documentation

Retrieve full index from cache and build "theindex.org".

PROJECT is the project the index relates to. DIRECTORY is the publishing directory.

Source Code

;; Defined in /usr/src/emacs/lisp/org/ox-publish.el.gz
(defun org-publish-index-generate-theindex (project directory)
  "Retrieve full index from cache and build \"theindex.org\".
PROJECT is the project the index relates to.  DIRECTORY is the
publishing directory."
  (let ((all-files (org-publish-get-base-files project))
	full-index)
    ;; Compile full index and sort it alphabetically.
    (dolist (file all-files
		  (setq full-index
			(sort (nreverse full-index)
			      (lambda (a b) (string< (downcase (car a))
						     (downcase (car b)))))))
      (let ((index (org-publish-cache-get-file-property file :index)))
	(dolist (term index)
	  (unless (member term full-index) (push term full-index)))))
    ;; Write "theindex.inc" in DIRECTORY.
    (with-temp-file (expand-file-name "theindex.inc" directory)
      (let ((current-letter nil) (last-entry nil))
	(dolist (idx full-index)
	  (let* ((entry (org-split-string (car idx) "!"))
		 (letter (upcase (substring (car entry) 0 1)))
		 ;; Transform file into a path relative to publishing
		 ;; directory.
		 (file (file-relative-name
			(nth 1 idx)
			(plist-get (cdr project) :base-directory))))
	    ;; Check if another letter has to be inserted.
	    (unless (string= letter current-letter)
	      (insert (format "* %s\n" letter)))
	    ;; Compute the first difference between last entry and
	    ;; current one: it tells the level at which new items
	    ;; should be added.
	    (let* ((rank
		    (if (equal entry last-entry) (1- (length entry))
		      (cl-loop for n from 0 to (length entry)
			       unless (equal (nth n entry) (nth n last-entry))
			       return n)))
		   (len (length (nthcdr rank entry))))
	      ;; For each term after the first difference, create
	      ;; a new sub-list with the term as body.  Moreover,
	      ;; linkify the last term.
	      (dotimes (n len)
		(insert
		 (concat
		  (make-string (* (+ rank n) 2) ?\s) "  - "
		  (if (not (= (1- len) n)) (nth (+ rank n) entry)
		    ;; Last term: Link it to TARGET, if possible.
		    (let ((target (nth 2 idx)))
		      (format
		       "[[%s][%s]]"
		       ;; Destination.
		       (pcase (car target)
			 (`nil (format "file:%s" file))
			 (`id (format "id:%s" (cdr target)))
			 (`custom-id (format "file:%s::#%s" file (cdr target)))
			 (_ (format "file:%s::*%s" file (cdr target))))
		       ;; Description.
		       (car (last entry)))))
		  "\n"))))
	    (setq current-letter letter last-entry entry))))
      ;; Create "theindex.org", if it doesn't exist yet, and provide
      ;; a default index file.
      (let ((index.org (expand-file-name "theindex.org" directory)))
	(unless (file-exists-p index.org)
	  (with-temp-file index.org
	    (insert "#+TITLE: Index\n\n#+INCLUDE: \"theindex.inc\"\n\n")))))))