7

Inside my org-mode documents, I'd like to do sub-TOCs for individual sections and subsections.

For example:

#+TOC: headlines 1         # This is the "main" table of contents,
                           # showing just the level-1 headings

* Business operations      # This is a level-1 heading

{{{SUBTOC}}}               # Inserts just the *level-2* headings for this *level-1* section

** Services                # This is a level-2 heading

{{{SUBTOC}}}               # Shows just the *level-3* headings for this *level-2* section

*** Statements of work
*** Changes to statements of work
*** No obligation to agree to statement of work

** Sales of goods          # The next level-2 heading

{{{SUBTOC}}}

etc.

Any suggestions?

4
  • 3
    Is it acceptable if these TOCs show up only after exporting? Or do they need to be updated directly in the buffer?
    – Malabarba
    Oct 17, 2014 at 11:02
  • What are you exporting to ? Oct 23, 2014 at 4:08
  • You haven't specified relevant backends. Please also see permalink.gmane.org/gmane.emacs.orgmode/91819. From the answers you got there, it's trivial to write a filter for LaTeX (see org-export-filter-headline-functions)
    – rasmus
    Dec 31, 2014 at 9:59
  • Now implemented in Org 8.3 by Nicolas Goaziou in commit b07e2f6ff1feddde83506b7fdb370bfe8e0a5337
    – rasmus
    Jan 11, 2015 at 22:46

2 Answers 2

3

New answer (implemented in Org 8.3)

You can do this with the local paramater to the #+TOC keyword. For example:

#+TOC: headlines 1 local

(example from the manual)

See the details in Nicolas Goaziou's commit here

Old answer:

Following the tips you got the last time you asked this question, the following code emerges that only works with LaTeX. For other backends you probably better off waiting for Nicolas' patch.

The code

(defun rasmus/get-org-headline-string-element  (headline backend info)
  "Return the org element representation of an element."
  (let ((prop-point (next-property-change 0 headline)))
(if prop-point (plist-get (text-properties-at prop-point headline) :parent))))

(defcustom rasmus/org-latex-subtoc-command
  (cons
   "\\startcontents[level-%s]\n\\printcontents[level-%s]{}{0}{\\setcounter{tocdepth}{%s}}"
   "\\stopcontents[level-%s]")
  "Command to wrap HEADLINE in when generating a subtoc")

(defun rasmus/org-latex-subtoc (headline backend info)
  "Insert a subtoc on headings which have non-nil property subtoc."
  (when (org-export-derived-backend-p backend 'latex)
(let ((elm (rasmus/get-org-headline-string-element headline backend info)))
  (when (and elm (org-element-property :SUBTOC elm))
    (let ((level (1+ (org-element-property :level elm)))
      (id (org-export-get-headline-id elm info)))
      (with-temp-buffer
    (insert headline)
    (goto-char (point-min))
    (forward-line (if (>= level (plist-get info :headline-levels)) 1 2))
    (insert (format (car rasmus/org-latex-subtoc-command) id id level) "\n")
    (goto-char (point-max))
    (insert (format (cdr rasmus/org-latex-subtoc-command) id) "\n")
    (buffer-string)))))))

(add-to-list 'org-export-filter-headline-functions 'rasmus/org-latex-subtoc)

You can optimize the code as you see fit.

Example

(let ((cont "# In reality you must load titletoc before hyperref.\n# use another filter for that or add it to `org-latex-packages-alist'\n#+LATEX_HEADER_EXTRA: \\usepackage{titletoc}\n\n#+OPTIONS: toc:nil\n\n#+TOC: headlines 1\n* Business operations\n  :PROPERTIES:\n  :subtoc:   t\n  :END:\n\n** Services \n   :PROPERTIES:\n   :subtoc:   t\n   :END:\n\n*** Statements of work\n*** Changes to statements of work\n*** No obligation to agree to statement of work\n\n** Sales of goods\n* Another sec\n"))
  (with-temp-buffer (insert cont) (require 'ox-latex) (org-latex-export-as-latex nil nil nil t)))

Output of example

\setcounter{tocdepth}{1}
\tableofcontents
\section{Business operations}
\label{sec-1}
\startcontents[level-sec-1]
\printcontents[level-sec-1]{}{0}{\setcounter{tocdepth}{2}}

\subsection{Services}
\startcontents[level-sec-1-1]
\printcontents[level-sec-1-1]{}{0}{\setcounter{tocdepth}{3}}
\label{sec-1-1}

\subsubsection{Statements of work}
\label{sec-1-1-1}
\subsubsection{Changes to statements of work}
\label{sec-1-1-2}
\subsubsection{No obligation to agree to statement of work}
\label{sec-1-1-3}

\stopcontents[level-sec-1-1]
\subsection{Sales of goods}
\label{sec-1-2}
\stopcontents[level-sec-1]
\section{Another sec}
\label{sec-2}

Notes

  • Do be aware of the note in the example:

    In reality you must load titletoc before hyperref. use another filter for that or add it to `org-latex-packages-alist' For more info see here.

  • rasmus/get-org-headline-string-element only works with headings that contains not only (E.g. it won't work on * ~verb~ or * =code=).

2

I don't think what you ask for is supported by org-mode. As far as I know, org-mode manages one TOC per export, the only exceptions being for tables or figures listings.

What I do suggest is a somehow manual solution, if you really want the TOC code generated automatically. Once all the subsections are defined, export each section in which you want a subheadings TOC as a subtree export (C-s in the C-c C-e export menu), asking for a 1-level TOC (your #+TOC line). Export in a buffer, and copy the TOC code, then insert it back in your document, enclosed in convenient markup (corresponding to what you export to).

Depending on the export backend, this makes sense or doesn't. For LaTeX, I suggest looking for \tableofcontents options.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.